From db1701742fc763459bfd438def9dfc5c52aa09cc Mon Sep 17 00:00:00 2001 From: Charles Pillar Date: Thu, 3 May 2007 17:30:12 +0200 Subject: [PATCH] --- yaml --- r: 55979 b: refs/heads/master c: 529fa5473123a9e81e711a92e46fba732c4264ed h: refs/heads/master i: 55977: 76d390fa0a8d58dde8046936a3ee5d9cacdd3800 55975: 9a4a4b20db2c8d631c171bb8c19a4dd26aba640f v: v3 --- [refs] | 2 +- trunk/CREDITS | 44 +- trunk/Documentation/ABI/removed/devfs | 2 +- trunk/Documentation/DocBook/kernel-api.tmpl | 4 - trunk/Documentation/MSI-HOWTO.txt | 6 +- trunk/Documentation/SubmitChecklist | 10 +- trunk/Documentation/SubmittingPatches | 3 +- trunk/Documentation/arm/Interrupts | 2 +- .../arm/Samsung-S3C24XX/H1940.txt | 4 +- trunk/Documentation/auxdisplay/cfag12864b | 6 +- trunk/Documentation/binfmt_misc.txt | 2 +- trunk/Documentation/block/ioprio.txt | 8 +- .../Documentation/cpu-freq/cpufreq-stats.txt | 2 +- trunk/Documentation/cpu-hotplug.txt | 9 +- trunk/Documentation/crypto/api-intro.txt | 6 +- trunk/Documentation/device-mapper/delay.txt | 26 - trunk/Documentation/driver-model/platform.txt | 4 +- trunk/Documentation/dvb/README.dvb-usb | 2 +- trunk/Documentation/dvb/contributors.txt | 2 +- trunk/Documentation/fb/arkfb.txt | 68 - trunk/Documentation/fb/aty128fb.txt | 4 +- trunk/Documentation/fb/framebuffer.txt | 16 +- trunk/Documentation/fb/imacfb.txt | 2 +- trunk/Documentation/fb/sstfb.txt | 4 +- trunk/Documentation/fb/vt8623fb.txt | 64 - .../feature-removal-schedule.txt | 17 +- trunk/Documentation/filesystems/Locking | 6 +- trunk/Documentation/filesystems/hpfs.txt | 2 +- trunk/Documentation/filesystems/ntfs.txt | 2 +- trunk/Documentation/filesystems/proc.txt | 2 +- trunk/Documentation/filesystems/relay.txt | 2 +- trunk/Documentation/filesystems/xip.txt | 2 +- trunk/Documentation/fujitsu/frv/gdbstub.txt | 2 +- trunk/Documentation/gpio.txt | 4 +- trunk/Documentation/hwmon/adm1026 | 2 +- trunk/Documentation/hwmon/gl518sm | 2 +- trunk/Documentation/hwmon/lm83 | 2 +- trunk/Documentation/hwmon/sis5595 | 2 +- trunk/Documentation/hwmon/via686a | 2 +- trunk/Documentation/hwmon/w83792d | 2 +- trunk/Documentation/i2c/busses/i2c-i810 | 2 +- trunk/Documentation/i2c/busses/i2c-sis96x | 2 +- trunk/Documentation/i2c/busses/i2c-via | 2 +- trunk/Documentation/i2c/busses/i2c-viapro | 2 +- trunk/Documentation/i2c/i2c-protocol | 2 +- trunk/Documentation/i2o/README | 4 +- trunk/Documentation/i386/boot.txt | 101 +- trunk/Documentation/input/atarikbd.txt | 4 +- trunk/Documentation/input/xpad.txt | 6 +- trunk/Documentation/isdn/CREDITS | 4 +- trunk/Documentation/isdn/README | 2 +- trunk/Documentation/isdn/README.icn | 4 +- trunk/Documentation/java.txt | 2 +- trunk/Documentation/kernel-docs.txt | 2 +- trunk/Documentation/kernel-parameters.txt | 8 + trunk/Documentation/m68k/README.buddha | 2 +- trunk/Documentation/magic-number.txt | 2 +- trunk/Documentation/md.txt | 72 +- trunk/Documentation/netlabel/introduction.txt | 2 +- trunk/Documentation/networking/6pack.txt | 2 +- trunk/Documentation/networking/NAPI_HOWTO.txt | 2 +- .../Documentation/networking/packet_mmap.txt | 2 +- trunk/Documentation/networking/slicecom.hun | 2 +- trunk/Documentation/networking/slicecom.txt | 4 +- trunk/Documentation/networking/tms380tr.txt | 42 +- trunk/Documentation/networking/udplite.txt | 2 +- trunk/Documentation/networking/wan-router.txt | 4 +- trunk/Documentation/pci.txt | 2 +- trunk/Documentation/pcieaer-howto.txt | 2 +- trunk/Documentation/pnp.txt | 2 +- trunk/Documentation/power/swsusp.txt | 2 +- trunk/Documentation/power/userland-swsusp.txt | 26 +- .../powerpc/booting-without-of.txt | 4 +- trunk/Documentation/s390/Debugging390.txt | 2 +- trunk/Documentation/scsi/aacraid.txt | 4 +- trunk/Documentation/scsi/aha152x.txt | 2 +- trunk/Documentation/scsi/aic7xxx.txt | 2 +- trunk/Documentation/scsi/aic7xxx_old.txt | 2 +- trunk/Documentation/scsi/ncr53c8xx.txt | 2 +- trunk/Documentation/scsi/st.txt | 2 +- trunk/Documentation/scsi/sym53c8xx_2.txt | 2 +- trunk/Documentation/scsi/tmscsim.txt | 2 +- trunk/Documentation/sonypi.txt | 2 +- trunk/Documentation/sound/oss/mwave | 2 +- trunk/Documentation/sysctl/kernel.txt | 4 +- trunk/Documentation/usb/CREDITS | 2 +- trunk/Documentation/usb/usb-serial.txt | 6 +- .../Documentation/video4linux/README.pvrusb2 | 2 +- trunk/Documentation/video4linux/Zoran | 2 +- trunk/Documentation/video4linux/meye.txt | 2 +- trunk/Documentation/video4linux/ov511.txt | 4 +- trunk/Documentation/vm/slabinfo.c | 426 +- trunk/MAINTAINERS | 18 +- trunk/arch/arm/Kconfig | 1 - trunk/arch/arm/Makefile | 5 - trunk/arch/arm/kernel/head-nommu.S | 2 +- trunk/arch/arm/kernel/head.S | 2 +- trunk/arch/arm/kernel/init_task.c | 2 +- trunk/arch/arm/kernel/module.c | 4 +- trunk/arch/arm/kernel/smp.c | 4 +- trunk/arch/arm/kernel/vmlinux.lds.S | 12 +- trunk/arch/arm/mach-at91/Kconfig | 2 +- trunk/arch/arm/mach-omap1/Kconfig | 7 +- trunk/arch/arm/mach-omap1/Makefile | 1 + trunk/arch/arm/mach-omap1/board-fsample.c | 2 +- trunk/arch/arm/mach-omap1/board-h3.c | 2 +- trunk/arch/arm/mach-omap1/board-innovator.c | 2 +- trunk/arch/arm/mach-omap1/board-perseus2.c | 2 +- trunk/arch/arm/mach-omap1/devices.c | 71 +- trunk/arch/arm/mach-omap1/io.c | 4 +- trunk/arch/arm/mach-omap1/mailbox.c | 206 - trunk/arch/arm/mach-omap2/Kconfig | 2 - trunk/arch/arm/mach-omap2/board-h4.c | 14 - trunk/arch/arm/mach-omap2/devices.c | 66 +- trunk/arch/arm/mach-omap2/gpmc.c | 12 +- trunk/arch/arm/mach-omap2/io.c | 21 +- trunk/arch/arm/mach-omap2/mailbox.c | 318 -- trunk/arch/arm/mach-s3c2410/sleep.S | 2 +- trunk/arch/arm/mm/Kconfig | 32 +- trunk/arch/arm/mm/Makefile | 3 - trunk/arch/arm/mm/abort-ev7.S | 32 - trunk/arch/arm/mm/cache-v7.S | 253 -- trunk/arch/arm/mm/context.c | 17 +- trunk/arch/arm/mm/proc-macros.S | 12 - trunk/arch/arm/mm/proc-v7.S | 262 -- trunk/arch/arm/plat-omap/Kconfig | 13 - trunk/arch/arm/plat-omap/Makefile | 5 +- trunk/arch/arm/plat-omap/clock.c | 37 - trunk/arch/arm/plat-omap/common.c | 8 +- trunk/arch/arm/plat-omap/debug-leds.c | 314 -- trunk/arch/arm/plat-omap/devices.c | 74 +- trunk/arch/arm/plat-omap/dma.c | 25 +- trunk/arch/arm/plat-omap/dmtimer.c | 2 +- trunk/arch/arm/plat-omap/fb.c | 305 +- trunk/arch/arm/plat-omap/gpio.c | 3 +- trunk/arch/arm/plat-omap/mailbox.c | 509 --- trunk/arch/arm/plat-omap/mailbox.h | 100 - trunk/arch/arm/plat-omap/sram.c | 56 +- trunk/arch/arm/plat-omap/usb.c | 199 +- trunk/arch/arm/plat-s3c24xx/sleep.S | 2 +- trunk/arch/avr32/Makefile | 2 +- trunk/arch/avr32/kernel/process.c | 6 +- trunk/arch/avr32/kernel/ptrace.c | 2 +- trunk/arch/avr32/kernel/syscall_table.S | 1 - trunk/arch/avr32/kernel/traps.c | 2 +- trunk/arch/avr32/kernel/vmlinux.lds.c | 2 +- trunk/arch/avr32/mach-at32ap/clock.c | 2 +- trunk/arch/avr32/mm/dma-coherent.c | 12 +- trunk/arch/blackfin/kernel/asm-offsets.c | 2 +- trunk/arch/blackfin/kernel/ptrace.c | 6 +- trunk/arch/cris/arch-v32/drivers/Kconfig | 2 +- trunk/arch/frv/Kconfig | 6 +- trunk/arch/frv/kernel/entry.S | 10 - trunk/arch/frv/kernel/gdb-stub.c | 12 +- trunk/arch/frv/kernel/process.c | 4 - trunk/arch/frv/kernel/setup.c | 4 +- trunk/arch/frv/mm/elf-fdpic.c | 1 - trunk/arch/frv/mm/pgalloc.c | 22 +- trunk/arch/h8300/Kconfig.debug | 4 +- trunk/arch/h8300/kernel/asm-offsets.c | 2 +- trunk/arch/h8300/kernel/syscalls.S | 78 +- trunk/arch/i386/Kconfig | 4 +- trunk/arch/i386/Kconfig.cpu | 4 +- trunk/arch/i386/boot/video.S | 4 +- trunk/arch/i386/kernel/cpu/intel_cacheinfo.c | 2 - .../arch/i386/kernel/cpu/mcheck/therm_throt.c | 4 +- trunk/arch/i386/kernel/cpu/transmeta.c | 6 +- trunk/arch/i386/kernel/cpuid.c | 2 - trunk/arch/i386/kernel/head.S | 38 + trunk/arch/i386/kernel/microcode.c | 59 +- trunk/arch/i386/kernel/msr.c | 2 - trunk/arch/i386/kernel/paravirt.c | 1 + trunk/arch/i386/kernel/syscall_table.S | 3 - trunk/arch/i386/kernel/traps.c | 2 +- trunk/arch/i386/kernel/vmlinux.lds.S | 6 + trunk/arch/i386/mach-generic/probe.c | 2 + trunk/arch/i386/mach-voyager/voyager_basic.c | 4 +- trunk/arch/i386/pci/init.c | 2 +- trunk/arch/ia64/Kconfig | 2 +- trunk/arch/ia64/ia32/ia32_entry.S | 39 +- trunk/arch/ia64/ia32/ia32_signal.c | 65 +- trunk/arch/ia64/kernel/entry.S | 30 +- trunk/arch/ia64/kernel/err_inject.c | 2 - trunk/arch/ia64/kernel/iosapic.c | 2 +- trunk/arch/ia64/kernel/irq_ia64.c | 27 +- trunk/arch/ia64/kernel/mca.c | 2 +- trunk/arch/ia64/kernel/palinfo.c | 2 - trunk/arch/ia64/kernel/process.c | 8 +- trunk/arch/ia64/kernel/relocate_kernel.S | 11 +- trunk/arch/ia64/kernel/salinfo.c | 2 - trunk/arch/ia64/kernel/setup.c | 2 +- trunk/arch/ia64/kernel/sigframe.h | 2 +- trunk/arch/ia64/kernel/signal.c | 71 +- trunk/arch/ia64/kernel/smp.c | 68 - trunk/arch/ia64/kernel/topology.c | 2 - trunk/arch/ia64/kernel/traps.c | 6 +- trunk/arch/ia64/kernel/unwind.c | 9 +- trunk/arch/ia64/mm/tlb.c | 6 +- trunk/arch/ia64/sn/kernel/irq.c | 58 +- trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c | 65 +- trunk/arch/m32r/Kconfig | 4 - trunk/arch/m32r/mm/mmu.S | 22 +- trunk/arch/m68knommu/Kconfig.debug | 2 +- trunk/arch/m68knommu/kernel/asm-offsets.c | 2 +- trunk/arch/mips/Kconfig | 6 +- trunk/arch/mips/Makefile | 2 +- trunk/arch/mips/kernel/asm-offsets.c | 2 +- trunk/arch/mips/kernel/smtc.c | 2 +- trunk/arch/mips/pci/fixup-sb1250.c | 4 +- trunk/arch/parisc/kernel/asm-offsets.c | 2 +- trunk/arch/powerpc/Kconfig | 24 +- trunk/arch/powerpc/Kconfig.debug | 2 +- trunk/arch/powerpc/boot/dts/mpc832x_mds.dts | 2 +- trunk/arch/powerpc/boot/dts/mpc834x_mds.dts | 4 +- trunk/arch/powerpc/configs/celleb_defconfig | 129 +- trunk/arch/powerpc/kernel/asm-offsets.c | 18 +- trunk/arch/powerpc/kernel/irq.c | 2 +- trunk/arch/powerpc/kernel/lparmap.c | 3 +- trunk/arch/powerpc/kernel/pci_64.c | 37 +- trunk/arch/powerpc/kernel/prom.c | 47 +- trunk/arch/powerpc/kernel/swsusp.c | 4 + trunk/arch/powerpc/kernel/sysfs.c | 2 - trunk/arch/powerpc/lib/Makefile | 2 + trunk/arch/powerpc/lib/rheap.c | 117 +- trunk/arch/powerpc/mm/Makefile | 1 - trunk/arch/powerpc/mm/hash_low_64.S | 5 +- trunk/arch/powerpc/mm/hash_native_64.c | 37 +- trunk/arch/powerpc/mm/hash_utils_64.c | 142 +- trunk/arch/powerpc/mm/hugetlbpage.c | 548 ++- trunk/arch/powerpc/mm/init_64.c | 17 +- trunk/arch/powerpc/mm/mem.c | 25 - trunk/arch/powerpc/mm/mmu_context_64.c | 10 - trunk/arch/powerpc/mm/numa.c | 3 - trunk/arch/powerpc/mm/ppc_mmu_32.c | 2 +- trunk/arch/powerpc/mm/slb.c | 11 + trunk/arch/powerpc/mm/slb_low.S | 52 +- trunk/arch/powerpc/mm/slice.c | 633 --- trunk/arch/powerpc/mm/tlb_32.c | 4 +- trunk/arch/powerpc/mm/tlb_64.c | 12 +- trunk/arch/powerpc/oprofile/op_model_cell.c | 2 +- .../arch/powerpc/platforms/83xx/mpc8313_rdb.c | 2 - .../arch/powerpc/platforms/83xx/mpc832x_rdb.c | 2 - .../arch/powerpc/platforms/83xx/mpc834x_itx.c | 2 - .../arch/powerpc/platforms/83xx/mpc834x_mds.c | 2 - .../powerpc/platforms/86xx/mpc86xx_hpcn.c | 7 +- .../arch/powerpc/platforms/86xx/mpc86xx_smp.c | 2 +- .../powerpc/platforms/8xx/mpc86xads_setup.c | 2 +- .../powerpc/platforms/8xx/mpc885ads_setup.c | 2 +- trunk/arch/powerpc/platforms/cell/Kconfig | 15 - .../powerpc/platforms/cell/io-workarounds.c | 2 +- trunk/arch/powerpc/platforms/cell/pervasive.c | 6 +- trunk/arch/powerpc/platforms/cell/spu_base.c | 9 +- .../powerpc/platforms/cell/spufs/Makefile | 2 +- .../powerpc/platforms/cell/spufs/context.c | 4 +- .../arch/powerpc/platforms/cell/spufs/file.c | 80 +- .../platforms/cell/spufs/lscsa_alloc.c | 181 - .../powerpc/platforms/cell/spufs/switch.c | 28 +- trunk/arch/powerpc/platforms/celleb/pci.c | 1 - .../arch/powerpc/platforms/celleb/scc_epci.c | 8 +- trunk/arch/powerpc/platforms/celleb/setup.c | 2 +- trunk/arch/powerpc/platforms/iseries/Kconfig | 4 +- trunk/arch/powerpc/platforms/pseries/eeh.c | 98 +- .../powerpc/platforms/pseries/eeh_driver.c | 17 +- trunk/arch/powerpc/platforms/pseries/iommu.c | 3 +- trunk/arch/powerpc/platforms/pseries/kexec.c | 1 - trunk/arch/powerpc/sysdev/commproc.c | 20 +- trunk/arch/powerpc/sysdev/cpm2_common.c | 21 +- trunk/arch/powerpc/sysdev/fsl_soc.c | 2 +- trunk/arch/powerpc/sysdev/qe_lib/qe.c | 29 +- trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c | 5 +- trunk/arch/powerpc/sysdev/qe_lib/ucc_slow.c | 7 +- trunk/arch/ppc/8xx_io/commproc.c | 22 +- trunk/arch/ppc/kernel/asm-offsets.c | 2 +- trunk/arch/ppc/lib/Makefile | 3 + trunk/arch/ppc/lib/rheap.c | 692 +++ trunk/arch/ppc/platforms/mpc866ads_setup.c | 2 +- trunk/arch/ppc/syslib/cpm2_common.c | 23 +- trunk/arch/ppc/syslib/ipic.c | 2 +- trunk/arch/s390/Kconfig | 49 +- trunk/arch/s390/appldata/appldata_base.c | 2 - trunk/arch/s390/crypto/Kconfig | 2 +- trunk/arch/s390/defconfig | 234 +- trunk/arch/s390/hypfs/inode.c | 2 +- trunk/arch/s390/kernel/asm-offsets.c | 2 +- trunk/arch/s390/kernel/ipl.c | 26 +- trunk/arch/s390/kernel/smp.c | 2 - trunk/arch/s390/mm/fault.c | 5 +- trunk/arch/sh/Kconfig | 29 +- trunk/arch/sh/boards/landisk/setup.c | 1 - trunk/arch/sh/boards/se/7751/setup.c | 2 +- trunk/arch/sh/drivers/Makefile | 3 +- trunk/arch/sh/drivers/dma/Kconfig | 20 +- trunk/arch/sh/drivers/dma/Makefile | 4 +- trunk/arch/sh/drivers/dma/dmabrg.c | 196 - trunk/arch/sh/kernel/cpu/sh2a/Makefile | 5 +- trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c | 55 - trunk/arch/sh/kernel/cpu/sh2a/probe.c | 1 - trunk/arch/sh/kernel/cpu/sh3/entry.S | 2 +- trunk/arch/sh/kernel/cpu/sh3/ex.S | 13 +- trunk/arch/sh/kernel/cpu/sh4/Makefile | 6 +- trunk/arch/sh/kernel/cpu/sh4/ex.S | 62 + trunk/arch/sh/kernel/cpu/sh4/fpu.c | 3 +- trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c | 2 +- trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c | 2 +- trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c | 2 +- trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c | 2 +- trunk/arch/sh/kernel/process.c | 16 +- trunk/arch/sh/kernel/setup.c | 2 +- trunk/arch/sh/kernel/sh_ksyms.c | 2 + trunk/arch/sh/kernel/signal.c | 13 +- trunk/arch/sh/kernel/stacktrace.c | 2 +- trunk/arch/sh/kernel/syscalls.S | 1 - trunk/arch/sh/kernel/time.c | 172 +- trunk/arch/sh/kernel/timers/timer-tmu.c | 182 +- trunk/arch/sh/kernel/traps.c | 20 +- trunk/arch/sh/kernel/vsyscall/vsyscall.c | 2 +- trunk/arch/sh/lib/delay.c | 5 +- trunk/arch/sh/mm/Kconfig | 7 - trunk/arch/sh/mm/fault.c | 2 +- trunk/arch/sh/mm/init.c | 2 - trunk/arch/sparc/kernel/asm-offsets.c | 2 +- trunk/arch/sparc/kernel/systbls.S | 2 - trunk/arch/sparc64/kernel/ebus.c | 3 +- trunk/arch/sparc64/kernel/kprobes.c | 11 +- trunk/arch/sparc64/kernel/pci.c | 47 +- trunk/arch/sparc64/kernel/pci_common.c | 240 +- trunk/arch/sparc64/kernel/pci_fire.c | 189 +- trunk/arch/sparc64/kernel/pci_impl.h | 130 +- trunk/arch/sparc64/kernel/pci_iommu.c | 4 +- trunk/arch/sparc64/kernel/pci_psycho.c | 377 +- trunk/arch/sparc64/kernel/pci_sabre.c | 490 +- trunk/arch/sparc64/kernel/pci_schizo.c | 472 +- trunk/arch/sparc64/kernel/pci_sun4v.c | 378 +- trunk/arch/sparc64/kernel/prom.c | 19 +- trunk/arch/sparc64/kernel/sbus.c | 12 +- trunk/arch/sparc64/kernel/sys_sparc32.c | 2 +- trunk/arch/sparc64/kernel/systbls.S | 3 - trunk/arch/sparc64/kernel/traps.c | 1 - trunk/arch/sparc64/mm/fault.c | 45 +- trunk/arch/um/Kconfig | 19 +- trunk/arch/um/Kconfig.scsi | 58 + trunk/arch/um/defconfig | 2 +- trunk/arch/um/include/common-offsets.h | 2 - trunk/arch/um/include/kern_util.h | 3 - trunk/arch/um/include/os.h | 1 + .../arch/um/include/sysdep-i386/archsetjmp.h | 2 +- .../um/include/sysdep-x86_64/archsetjmp.h | 2 +- trunk/arch/um/kernel/dyn.lds.S | 2 - trunk/arch/um/kernel/init_task.c | 30 +- trunk/arch/um/kernel/irq.c | 115 +- trunk/arch/um/kernel/skas/process.c | 13 +- trunk/arch/um/kernel/tt/exec_kern.c | 2 +- trunk/arch/um/kernel/tt/process_kern.c | 2 +- trunk/arch/um/kernel/um_arch.c | 2 +- trunk/arch/um/kernel/uml.lds.S | 2 - trunk/arch/um/os-Linux/process.c | 2 - trunk/arch/um/os-Linux/signal.c | 50 +- trunk/arch/um/os-Linux/skas/mem.c | 2 +- trunk/arch/um/os-Linux/skas/process.c | 15 +- trunk/arch/um/os-Linux/sys-i386/signal.c | 8 +- trunk/arch/um/os-Linux/sys-x86_64/signal.c | 6 +- trunk/arch/um/os-Linux/util.c | 23 +- trunk/arch/v850/kernel/asm-offsets.c | 2 +- trunk/arch/v850/kernel/entry.S | 2 +- trunk/arch/x86_64/ia32/ia32entry.S | 3 - trunk/arch/x86_64/kernel/head64.c | 7 + trunk/arch/x86_64/kernel/io_apic.c | 2 +- trunk/arch/x86_64/kernel/irq.c | 2 +- trunk/arch/x86_64/kernel/mce.c | 2 - trunk/arch/x86_64/kernel/mce_amd.c | 2 - trunk/arch/x86_64/kernel/traps.c | 1 - trunk/arch/x86_64/kernel/vsyscall.c | 2 +- trunk/arch/xtensa/kernel/asm-offsets.c | 2 +- trunk/arch/xtensa/kernel/pci-dma.c | 2 +- trunk/block/as-iosched.c | 2 +- trunk/block/genhd.c | 53 - trunk/block/ll_rw_blk.c | 11 +- trunk/crypto/Kconfig | 2 +- trunk/crypto/cryptomgr.c | 7 +- trunk/drivers/Makefile | 1 - trunk/drivers/acpi/dispatcher/dsmethod.c | 12 +- trunk/drivers/acpi/dispatcher/dsopcode.c | 3 +- trunk/drivers/acpi/dispatcher/dsutils.c | 7 +- trunk/drivers/acpi/dispatcher/dswstate.c | 9 +- trunk/drivers/acpi/ec.c | 39 +- trunk/drivers/acpi/events/evgpe.c | 5 +- trunk/drivers/acpi/events/evgpeblk.c | 3 +- trunk/drivers/acpi/events/evmisc.c | 20 +- trunk/drivers/acpi/events/evregion.c | 15 +- trunk/drivers/acpi/events/evrgnini.c | 3 +- trunk/drivers/acpi/events/evxface.c | 7 +- trunk/drivers/acpi/events/evxfevnt.c | 2 + trunk/drivers/acpi/executer/exconvrt.c | 5 +- trunk/drivers/acpi/executer/excreate.c | 6 +- trunk/drivers/acpi/executer/exdump.c | 17 +- trunk/drivers/acpi/executer/exmutex.c | 37 +- trunk/drivers/acpi/executer/exnames.c | 3 +- trunk/drivers/acpi/executer/exprep.c | 2 +- trunk/drivers/acpi/executer/exresop.c | 3 +- trunk/drivers/acpi/executer/exsystem.c | 30 +- trunk/drivers/acpi/executer/exutils.c | 104 +- trunk/drivers/acpi/hardware/hwsleep.c | 1 + trunk/drivers/acpi/namespace/nseval.c | 13 +- trunk/drivers/acpi/namespace/nsinit.c | 7 +- trunk/drivers/acpi/namespace/nswalk.c | 6 +- trunk/drivers/acpi/namespace/nsxfeval.c | 17 +- trunk/drivers/acpi/numa.c | 4 +- trunk/drivers/acpi/osl.c | 45 +- trunk/drivers/acpi/parser/psopcode.c | 618 +-- trunk/drivers/acpi/resources/rscalc.c | 3 +- trunk/drivers/acpi/resources/rscreate.c | 13 +- trunk/drivers/acpi/resources/rsdump.c | 8 +- trunk/drivers/acpi/resources/rsinfo.c | 2 +- trunk/drivers/acpi/resources/rslist.c | 7 +- trunk/drivers/acpi/resources/rsmisc.c | 4 +- trunk/drivers/acpi/resources/rsutils.c | 6 +- trunk/drivers/acpi/resources/rsxface.c | 3 + trunk/drivers/acpi/sleep/main.c | 68 +- trunk/drivers/acpi/sleep/proc.c | 13 +- trunk/drivers/acpi/tables/tbfadt.c | 6 +- trunk/drivers/acpi/tables/tbxface.c | 16 +- trunk/drivers/acpi/thermal.c | 104 +- trunk/drivers/acpi/utilities/utalloc.c | 1 + trunk/drivers/acpi/utilities/utcache.c | 3 +- trunk/drivers/acpi/utilities/utcopy.c | 4 +- trunk/drivers/acpi/utilities/utdebug.c | 4 +- trunk/drivers/acpi/utilities/utdelete.c | 1 - trunk/drivers/acpi/utilities/utglobal.c | 6 +- trunk/drivers/acpi/utilities/utmisc.c | 6 +- trunk/drivers/acpi/utilities/utmutex.c | 8 +- trunk/drivers/acpi/utilities/utresrc.c | 1 + trunk/drivers/acpi/utilities/utxface.c | 2 + trunk/drivers/ata/Kconfig | 3 +- trunk/drivers/ata/libata-acpi.c | 3 +- trunk/drivers/ata/libata-core.c | 10 +- trunk/drivers/ata/pata_pcmcia.c | 1 - trunk/drivers/ata/pata_qdi.c | 2 +- trunk/drivers/ata/pata_scc.c | 4 +- trunk/drivers/ata/sata_nv.c | 92 +- trunk/drivers/ata/sata_promise.c | 24 +- trunk/drivers/ata/sata_via.c | 8 - trunk/drivers/auxdisplay/Kconfig | 1 - trunk/drivers/base/devres.c | 32 +- trunk/drivers/base/platform.c | 2 +- trunk/drivers/base/topology.c | 3 - trunk/drivers/block/Kconfig | 4 +- trunk/drivers/block/loop.c | 6 +- trunk/drivers/block/nbd.c | 15 +- trunk/drivers/block/rd.c | 2 +- trunk/drivers/bluetooth/hci_ldisc.c | 10 +- trunk/drivers/bluetooth/hci_uart.h | 5 +- trunk/drivers/char/Kconfig | 14 +- trunk/drivers/char/drm/drm_dma.c | 2 +- trunk/drivers/char/drm/drm_vm.c | 2 +- trunk/drivers/char/drm/r300_reg.h | 2 +- trunk/drivers/char/genrtc.c | 4 +- trunk/drivers/char/hw_random/Kconfig | 14 - trunk/drivers/char/hw_random/Makefile | 1 - trunk/drivers/char/hw_random/pasemi-rng.c | 156 - trunk/drivers/char/ipmi/Kconfig | 2 - trunk/drivers/char/mmtimer.c | 4 +- trunk/drivers/char/n_tty.c | 29 +- trunk/drivers/char/pcmcia/Kconfig | 1 - trunk/drivers/char/pcmcia/cm4000_cs.c | 46 +- trunk/drivers/char/pcmcia/cm4040_cs.c | 7 +- trunk/drivers/char/rio/riocmd.c | 2 +- trunk/drivers/char/rocket.c | 3 + trunk/drivers/char/rocket_int.h | 2 + trunk/drivers/char/synclink_gt.c | 107 - trunk/drivers/char/tpm/Kconfig | 3 +- trunk/drivers/char/tty_io.c | 65 +- trunk/drivers/char/watchdog/Kconfig | 150 +- trunk/drivers/char/watchdog/Makefile | 2 +- trunk/drivers/char/watchdog/cpu5wdt.c | 14 +- trunk/drivers/char/watchdog/eurotechwdt.c | 22 +- trunk/drivers/char/watchdog/i8xx_tco.c | 571 +++ trunk/drivers/char/watchdog/i8xx_tco.h | 42 + trunk/drivers/char/watchdog/ibmasr.c | 11 +- trunk/drivers/char/watchdog/machzwd.c | 18 +- trunk/drivers/char/watchdog/mtx-1_wdt.c | 238 - trunk/drivers/char/watchdog/pcwd.c | 242 +- trunk/drivers/char/watchdog/pcwd_usb.c | 8 +- trunk/drivers/char/watchdog/s3c2410_wdt.c | 6 +- trunk/drivers/char/watchdog/sbc8360.c | 28 +- trunk/drivers/char/watchdog/w83627hf_wdt.c | 23 +- trunk/drivers/cpufreq/cpufreq.c | 3 - trunk/drivers/cpufreq/cpufreq_stats.c | 2 - trunk/drivers/crypto/Kconfig | 24 +- trunk/drivers/dma/Kconfig | 1 - trunk/drivers/edac/Kconfig | 1 - trunk/drivers/firewire/Kconfig | 61 - trunk/drivers/firewire/Makefile | 10 - trunk/drivers/firewire/fw-card.c | 560 --- trunk/drivers/firewire/fw-cdev.c | 961 ---- trunk/drivers/firewire/fw-device.c | 813 ---- trunk/drivers/firewire/fw-device.h | 146 - trunk/drivers/firewire/fw-iso.c | 163 - trunk/drivers/firewire/fw-ohci.c | 1943 -------- trunk/drivers/firewire/fw-ohci.h | 153 - trunk/drivers/firewire/fw-sbp2.c | 1147 ----- trunk/drivers/firewire/fw-topology.c | 537 --- trunk/drivers/firewire/fw-topology.h | 92 - trunk/drivers/firewire/fw-transaction.c | 910 ---- trunk/drivers/firewire/fw-transaction.h | 458 -- trunk/drivers/hid/hid-input.c | 4 + trunk/drivers/hwmon/Kconfig | 1 - trunk/drivers/hwmon/ams/ams-input.c | 2 +- trunk/drivers/hwmon/applesmc.c | 9 +- trunk/drivers/hwmon/coretemp.c | 2 - trunk/drivers/hwmon/hdaps.c | 2 +- trunk/drivers/i2c/Kconfig | 1 - trunk/drivers/i2c/busses/i2c-at91.c | 7 +- trunk/drivers/i2c/busses/i2c-pxa.c | 2 +- trunk/drivers/i2c/chips/tps65010.c | 2 +- trunk/drivers/ide/Kconfig | 15 - trunk/drivers/ide/Makefile | 2 +- trunk/drivers/ide/arm/bast-ide.c | 2 +- trunk/drivers/ide/arm/icside.c | 9 +- trunk/drivers/ide/arm/ide_arm.c | 2 +- trunk/drivers/ide/arm/rapide.c | 2 +- trunk/drivers/ide/cris/ide-cris.c | 4 +- trunk/drivers/ide/h8300/ide-h8300.c | 2 +- trunk/drivers/ide/ide-cd.c | 20 +- trunk/drivers/ide/ide-disk.c | 101 +- trunk/drivers/ide/ide-dma.c | 94 - trunk/drivers/ide/ide-floppy.c | 30 +- trunk/drivers/ide/ide-generic.c | 2 + trunk/drivers/ide/ide-io.c | 17 +- trunk/drivers/ide/ide-iops.c | 55 +- trunk/drivers/ide/ide-lib.c | 132 +- trunk/drivers/ide/ide-pnp.c | 2 +- trunk/drivers/ide/ide-probe.c | 3 - trunk/drivers/ide/ide-proc.c | 344 +- trunk/drivers/ide/ide-tape.c | 49 +- trunk/drivers/ide/ide.c | 470 +- trunk/drivers/ide/legacy/ali14xx.c | 3 +- trunk/drivers/ide/legacy/buddha.c | 2 +- trunk/drivers/ide/legacy/dtc2278.c | 3 +- trunk/drivers/ide/legacy/falconide.c | 2 +- trunk/drivers/ide/legacy/gayle.c | 2 +- trunk/drivers/ide/legacy/ht6560b.c | 3 +- trunk/drivers/ide/legacy/ide-cs.c | 2 +- trunk/drivers/ide/legacy/macide.c | 6 +- trunk/drivers/ide/legacy/q40ide.c | 2 +- trunk/drivers/ide/legacy/qd65xx.c | 7 +- trunk/drivers/ide/legacy/umc8672.c | 3 +- trunk/drivers/ide/mips/au1xxx-ide.c | 3 - trunk/drivers/ide/mips/swarm.c | 3 - trunk/drivers/ide/pci/aec62xx.c | 62 +- trunk/drivers/ide/pci/alim15x3.c | 97 +- trunk/drivers/ide/pci/amd74xx.c | 6 +- trunk/drivers/ide/pci/atiixp.c | 40 +- trunk/drivers/ide/pci/cmd64x.c | 90 +- trunk/drivers/ide/pci/cs5520.c | 20 +- trunk/drivers/ide/pci/cs5535.c | 33 +- trunk/drivers/ide/pci/delkin_cb.c | 2 +- trunk/drivers/ide/pci/hpt34x.c | 27 +- trunk/drivers/ide/pci/hpt366.c | 85 +- trunk/drivers/ide/pci/it8213.c | 39 +- trunk/drivers/ide/pci/it821x.c | 20 +- trunk/drivers/ide/pci/jmicron.c | 40 +- trunk/drivers/ide/pci/pdc202xx_new.c | 40 +- trunk/drivers/ide/pci/pdc202xx_old.c | 54 +- trunk/drivers/ide/pci/piix.c | 163 +- trunk/drivers/ide/pci/scc_pata.c | 21 +- trunk/drivers/ide/pci/serverworks.c | 31 +- trunk/drivers/ide/pci/sgiioc4.c | 2 +- trunk/drivers/ide/pci/siimage.c | 47 +- trunk/drivers/ide/pci/sis5513.c | 44 +- trunk/drivers/ide/pci/slc90e66.c | 24 +- trunk/drivers/ide/pci/tc86c001.c | 20 +- trunk/drivers/ide/pci/triflex.c | 15 +- trunk/drivers/ide/ppc/pmac.c | 2 - trunk/drivers/ide/setup-pci.c | 27 +- trunk/drivers/ieee1394/Kconfig | 3 - trunk/drivers/ieee1394/nodemgr.c | 2 +- trunk/drivers/infiniband/Kconfig | 8 - trunk/drivers/infiniband/Makefile | 1 - trunk/drivers/infiniband/core/Makefile | 4 +- trunk/drivers/infiniband/core/device.c | 2 - trunk/drivers/infiniband/core/uverbs.h | 6 +- trunk/drivers/infiniband/core/uverbs_cmd.c | 60 +- trunk/drivers/infiniband/core/uverbs_main.c | 11 +- .../infiniband/core/{umem.c => uverbs_mem.c} | 153 +- .../infiniband/hw/amso1100/c2_provider.c | 42 +- .../infiniband/hw/amso1100/c2_provider.h | 1 - .../infiniband/hw/cxgb3/iwch_provider.c | 28 +- .../infiniband/hw/cxgb3/iwch_provider.h | 1 - .../drivers/infiniband/hw/ehca/ehca_classes.h | 1 - trunk/drivers/infiniband/hw/ehca/ehca_irq.c | 6 - .../drivers/infiniband/hw/ehca/ehca_iverbs.h | 3 +- trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c | 69 +- trunk/drivers/infiniband/hw/ipath/ipath_mr.c | 38 +- .../drivers/infiniband/hw/ipath/ipath_verbs.h | 5 +- trunk/drivers/infiniband/hw/mlx4/Kconfig | 9 - trunk/drivers/infiniband/hw/mlx4/Makefile | 3 - trunk/drivers/infiniband/hw/mlx4/ah.c | 100 - trunk/drivers/infiniband/hw/mlx4/cq.c | 525 --- trunk/drivers/infiniband/hw/mlx4/doorbell.c | 216 - trunk/drivers/infiniband/hw/mlx4/mad.c | 339 -- trunk/drivers/infiniband/hw/mlx4/main.c | 651 --- trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h | 285 -- trunk/drivers/infiniband/hw/mlx4/mr.c | 184 - trunk/drivers/infiniband/hw/mlx4/qp.c | 1294 ------ trunk/drivers/infiniband/hw/mlx4/srq.c | 334 -- trunk/drivers/infiniband/hw/mlx4/user.h | 92 - .../infiniband/hw/mthca/mthca_provider.c | 38 +- .../infiniband/hw/mthca/mthca_provider.h | 1 - trunk/drivers/input/Kconfig | 1 - trunk/drivers/input/evdev.c | 2 +- trunk/drivers/input/misc/ixp4xx-beeper.c | 2 +- trunk/drivers/isdn/Kconfig | 1 - trunk/drivers/isdn/capi/Kconfig | 2 +- trunk/drivers/isdn/gigaset/usb-gigaset.c | 14 +- trunk/drivers/isdn/hardware/eicon/divasync.h | 2 +- trunk/drivers/isdn/hisax/hfc_usb.c | 4 +- trunk/drivers/kvm/Kconfig | 1 - trunk/drivers/kvm/kvm_main.c | 3 - trunk/drivers/leds/Kconfig | 1 - trunk/drivers/leds/leds-h1940.c | 2 +- trunk/drivers/macintosh/Kconfig | 2 +- trunk/drivers/macintosh/mediabay.c | 2 +- trunk/drivers/mca/mca-bus.c | 28 +- trunk/drivers/mca/mca-driver.c | 13 - trunk/drivers/md/Kconfig | 9 - trunk/drivers/md/Makefile | 1 - trunk/drivers/md/dm-bio-list.h | 26 - trunk/drivers/md/dm-crypt.c | 91 +- trunk/drivers/md/dm-delay.c | 383 -- trunk/drivers/md/dm-exception-store.c | 54 +- trunk/drivers/md/dm-hw-handler.h | 1 - trunk/drivers/md/dm-io.c | 232 +- trunk/drivers/md/dm-io.h | 83 +- trunk/drivers/md/dm-log.c | 77 +- trunk/drivers/md/dm-mpath.c | 3 - trunk/drivers/md/dm-raid1.c | 187 +- trunk/drivers/md/dm-table.c | 10 +- trunk/drivers/md/dm.c | 1 - trunk/drivers/md/kcopyd.c | 28 +- trunk/drivers/md/md.c | 162 +- trunk/drivers/md/raid1.c | 33 +- trunk/drivers/md/raid5.c | 4 +- trunk/drivers/media/Kconfig | 1 - .../media/dvb/dvb-usb/dvb-usb-remote.c | 2 +- trunk/drivers/media/dvb/frontends/dib7000m.c | 2 +- trunk/drivers/media/dvb/frontends/dib7000p.c | 2 +- trunk/drivers/media/dvb/frontends/tda10021.c | 2 +- trunk/drivers/media/dvb/frontends/ves1x93.c | 2 +- trunk/drivers/media/video/em28xx/em28xx-i2c.c | 2 +- .../drivers/media/video/em28xx/em28xx-video.c | 2 +- trunk/drivers/media/video/pwc/philips.txt | 6 +- trunk/drivers/media/video/usbvideo/vicam.c | 2 +- trunk/drivers/message/fusion/Kconfig | 1 - .../message/fusion/lsi/mpi_history.txt | 2 +- trunk/drivers/message/fusion/mptbase.c | 2 +- trunk/drivers/message/i2o/Kconfig | 1 - trunk/drivers/mfd/Kconfig | 1 - trunk/drivers/misc/Kconfig | 2 +- trunk/drivers/misc/asus-laptop.c | 66 +- trunk/drivers/misc/msi-laptop.c | 12 +- trunk/drivers/misc/sony-laptop.c | 8 +- trunk/drivers/misc/tifm_7xx1.c | 27 +- trunk/drivers/mmc/Kconfig | 11 +- trunk/drivers/mmc/card/Kconfig | 3 +- trunk/drivers/mmc/core/Kconfig | 1 + trunk/drivers/mmc/core/core.c | 10 +- trunk/drivers/mmc/host/Kconfig | 19 +- trunk/drivers/mmc/host/tifm_sd.c | 13 +- trunk/drivers/mtd/Kconfig | 1 - trunk/drivers/mtd/chips/Kconfig | 40 + trunk/drivers/mtd/chips/Makefile | 4 + trunk/drivers/mtd/chips/amd_flash.c | 1396 ++++++ trunk/drivers/mtd/chips/jedec.c | 935 ++++ trunk/drivers/mtd/chips/sharp.c | 601 +++ trunk/drivers/mtd/devices/block2mtd.c | 2 +- trunk/drivers/mtd/maps/Kconfig | 18 +- trunk/drivers/mtd/maps/Makefile | 2 + trunk/drivers/mtd/maps/arctic-mtd.c | 145 + trunk/drivers/mtd/maps/beech-mtd.c | 122 + trunk/drivers/mtd/maps/nettel.c | 2 +- trunk/drivers/mtd/maps/physmap_of.c | 2 +- trunk/drivers/mtd/mtdpart.c | 1 + trunk/drivers/mtd/nand/Kconfig | 21 +- trunk/drivers/mtd/nand/Makefile | 2 +- trunk/drivers/mtd/nand/at91_nand.c | 10 - .../drivers/mtd/nand/{cafe_nand.c => cafe.c} | 137 +- trunk/drivers/mtd/nand/cafe_ecc.c | 1381 ++++++ trunk/drivers/mtd/nand/nand_base.c | 11 +- trunk/drivers/mtd/nand/plat_nand.c | 150 - trunk/drivers/mtd/onenand/onenand_base.c | 2 +- trunk/drivers/net/3c509.c | 5 +- trunk/drivers/net/3c59x.c | 2 +- trunk/drivers/net/Kconfig | 16 - trunk/drivers/net/Makefile | 9 - trunk/drivers/net/atl1/atl1_main.c | 12 - trunk/drivers/net/atp.c | 8 +- trunk/drivers/net/bonding/bond_main.c | 2 +- trunk/drivers/net/e1000/e1000_main.c | 2 +- trunk/drivers/net/eepro.c | 2 +- trunk/drivers/net/eepro100.c | 2 +- trunk/drivers/net/epic100.c | 10 +- trunk/drivers/net/fs_enet/mac-scc.c | 2 +- trunk/drivers/net/hamradio/Kconfig | 2 +- trunk/drivers/net/irda/Kconfig | 14 - trunk/drivers/net/irda/Makefile | 1 - trunk/drivers/net/irda/donauboe.h | 2 +- trunk/drivers/net/irda/kingsun-sir.c | 657 --- trunk/drivers/net/ixgb/ixgb_ee.c | 2 +- trunk/drivers/net/meth.h | 2 +- trunk/drivers/net/mlx4/Makefile | 4 - trunk/drivers/net/mlx4/alloc.c | 179 - trunk/drivers/net/mlx4/catas.c | 70 - trunk/drivers/net/mlx4/cmd.c | 429 -- trunk/drivers/net/mlx4/cq.c | 254 -- trunk/drivers/net/mlx4/eq.c | 696 --- trunk/drivers/net/mlx4/fw.c | 775 ---- trunk/drivers/net/mlx4/fw.h | 167 - trunk/drivers/net/mlx4/icm.c | 379 -- trunk/drivers/net/mlx4/icm.h | 135 - trunk/drivers/net/mlx4/intf.c | 165 - trunk/drivers/net/mlx4/main.c | 936 ---- trunk/drivers/net/mlx4/mcg.c | 380 -- trunk/drivers/net/mlx4/mlx4.h | 348 -- trunk/drivers/net/mlx4/mr.c | 479 -- trunk/drivers/net/mlx4/pd.c | 102 - trunk/drivers/net/mlx4/profile.c | 238 - trunk/drivers/net/mlx4/qp.c | 280 -- trunk/drivers/net/mlx4/reset.c | 181 - trunk/drivers/net/mlx4/srq.c | 227 - trunk/drivers/net/natsemi.c | 1 + trunk/drivers/net/ne2k-pci.c | 3 +- trunk/drivers/net/pcmcia/ibmtr_cs.c | 14 +- trunk/drivers/net/phy/Kconfig | 1 - trunk/drivers/net/phy/phy.c | 6 +- trunk/drivers/net/skge.c | 4 +- trunk/drivers/net/sundance.c | 3 +- trunk/drivers/net/tg3.c | 11 +- trunk/drivers/net/tg3.h | 2 +- trunk/drivers/net/tulip/interrupt.c | 2 +- trunk/drivers/net/tulip/winbond-840.c | 2 +- trunk/drivers/net/tulip/xircom_cb.c | 2 +- trunk/drivers/net/typhoon.c | 2 +- trunk/drivers/net/ucc_geth.c | 30 +- trunk/drivers/net/wireless/Kconfig | 1 - trunk/drivers/net/wireless/airport.c | 2 +- trunk/drivers/net/wireless/bcm43xx/bcm43xx.h | 18 +- .../net/wireless/bcm43xx/bcm43xx_dma.c | 4 + .../net/wireless/bcm43xx/bcm43xx_main.c | 81 + .../net/wireless/bcm43xx/bcm43xx_main.h | 19 + .../drivers/net/wireless/prism54/isl_ioctl.c | 2 +- .../drivers/net/wireless/prism54/islpci_dev.c | 2 +- trunk/drivers/net/wireless/wavelan_cs.c | 4 +- trunk/drivers/net/wireless/wavelan_cs.p.h | 2 +- trunk/drivers/net/wireless/zd1211rw/zd_usb.c | 4 - trunk/drivers/net/yellowfin.c | 1 + trunk/drivers/parport/Kconfig | 1 - trunk/drivers/pci/pci-driver.c | 2 +- trunk/drivers/pnp/Kconfig | 1 - trunk/drivers/rtc/Kconfig | 5 +- trunk/drivers/rtc/rtc-rs5c313.c | 28 +- trunk/drivers/rtc/rtc-sh.c | 8 +- trunk/drivers/s390/{char => }/Kconfig | 111 +- trunk/drivers/s390/block/Kconfig | 11 +- trunk/drivers/s390/block/dasd.c | 8 +- trunk/drivers/s390/block/dasd_diag.c | 10 +- trunk/drivers/s390/block/dasd_eckd.c | 6 +- trunk/drivers/s390/block/dasd_ioctl.c | 4 +- trunk/drivers/s390/char/monreader.c | 14 +- trunk/drivers/s390/char/raw3270.c | 5 +- trunk/drivers/s390/char/sclp.h | 3 - trunk/drivers/s390/char/sclp_rw.c | 2 +- trunk/drivers/s390/char/sclp_sdias.c | 8 +- trunk/drivers/s390/char/zcore.c | 9 +- trunk/drivers/s390/cio/css.c | 3 +- trunk/drivers/s390/cio/css.h | 2 + trunk/drivers/s390/cio/device.c | 4 +- trunk/drivers/s390/cio/device_ops.c | 11 - trunk/drivers/s390/cio/qdio.c | 1 - trunk/drivers/s390/net/Kconfig | 8 +- trunk/drivers/s390/net/qeth_main.c | 2 +- trunk/drivers/s390/net/qeth_mpc.c | 4 +- trunk/drivers/s390/scsi/zfcp_aux.c | 98 +- trunk/drivers/s390/scsi/zfcp_dbf.c | 2 +- trunk/drivers/s390/scsi/zfcp_def.h | 41 - trunk/drivers/s390/scsi/zfcp_erp.c | 89 +- trunk/drivers/s390/scsi/zfcp_ext.h | 4 + trunk/drivers/s390/scsi/zfcp_fsf.c | 50 +- trunk/drivers/s390/scsi/zfcp_qdio.c | 51 +- trunk/drivers/s390/scsi/zfcp_scsi.c | 9 +- trunk/drivers/sbus/char/bpp.c | 2 +- trunk/drivers/scsi/aacraid/comminit.c | 3 +- trunk/drivers/scsi/aacraid/commsup.c | 6 +- trunk/drivers/scsi/aacraid/dpcsup.c | 6 +- trunk/drivers/scsi/aacraid/rx.c | 4 +- trunk/drivers/scsi/aic7xxx/aic79xx_pci.c | 2 +- trunk/drivers/scsi/aic94xx/Makefile | 2 +- trunk/drivers/scsi/ch.c | 9 +- trunk/drivers/scsi/dc395x.c | 6 +- trunk/drivers/scsi/dpt_i2o.c | 17 +- trunk/drivers/scsi/ide-scsi.c | 30 +- trunk/drivers/scsi/ipr.c | 349 +- trunk/drivers/scsi/ipr.h | 33 +- trunk/drivers/scsi/libsas/sas_scsi_host.c | 36 +- trunk/drivers/scsi/lpfc/lpfc.h | 33 +- trunk/drivers/scsi/lpfc/lpfc_attr.c | 212 +- trunk/drivers/scsi/lpfc/lpfc_crtn.h | 32 +- trunk/drivers/scsi/lpfc/lpfc_ct.c | 24 +- trunk/drivers/scsi/lpfc/lpfc_disc.h | 28 +- trunk/drivers/scsi/lpfc/lpfc_els.c | 552 ++- trunk/drivers/scsi/lpfc/lpfc_hbadisc.c | 884 ++-- trunk/drivers/scsi/lpfc/lpfc_hw.h | 11 +- trunk/drivers/scsi/lpfc/lpfc_init.c | 516 ++- trunk/drivers/scsi/lpfc/lpfc_mbox.c | 3 +- trunk/drivers/scsi/lpfc/lpfc_nportdisc.c | 307 +- trunk/drivers/scsi/lpfc/lpfc_scsi.c | 109 +- trunk/drivers/scsi/lpfc/lpfc_sli.c | 427 +- trunk/drivers/scsi/lpfc/lpfc_sli.h | 12 +- trunk/drivers/scsi/lpfc/lpfc_version.h | 6 +- trunk/drivers/scsi/megaraid.c | 20 +- trunk/drivers/scsi/megaraid.h | 4 +- trunk/drivers/scsi/megaraid/megaraid_mm.c | 2 +- trunk/drivers/scsi/mesh.c | 14 +- trunk/drivers/scsi/qla1280.c | 2 +- trunk/drivers/scsi/qla2xxx/qla_init.c | 44 +- trunk/drivers/scsi/qla2xxx/qla_isr.c | 15 +- trunk/drivers/scsi/qla2xxx/qla_os.c | 6 +- trunk/drivers/scsi/qla2xxx/qla_version.h | 2 +- trunk/drivers/scsi/qla4xxx/ql4_dbg.c | 4 - trunk/drivers/scsi/qla4xxx/ql4_glbl.h | 9 + trunk/drivers/scsi/qla4xxx/ql4_init.c | 18 +- trunk/drivers/scsi/qla4xxx/ql4_iocb.c | 18 +- trunk/drivers/scsi/qla4xxx/ql4_mbx.c | 19 +- trunk/drivers/scsi/qla4xxx/ql4_os.c | 9 +- trunk/drivers/scsi/scsi_error.c | 3 +- trunk/drivers/scsi/scsi_lib.c | 2 +- trunk/drivers/scsi/scsi_transport_fc.c | 158 +- trunk/drivers/scsi/tmscsim.c | 225 +- trunk/drivers/scsi/tmscsim.h | 12 +- trunk/drivers/serial/Kconfig | 1 - trunk/drivers/serial/cpm_uart/cpm_uart.h | 2 +- trunk/drivers/serial/cpm_uart/cpm_uart_core.c | 3 +- trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c | 6 +- trunk/drivers/serial/cpm_uart/cpm_uart_cpm2.c | 6 +- trunk/drivers/serial/sunzilog.c | 138 +- trunk/drivers/serial/sunzilog.h | 19 +- trunk/drivers/spi/Kconfig | 8 - trunk/drivers/spi/Makefile | 1 - trunk/drivers/spi/atmel_spi.c | 5 + trunk/drivers/spi/mpc52xx_psc_spi.c | 654 --- trunk/drivers/telephony/Kconfig | 1 - trunk/drivers/usb/Kconfig | 3 +- trunk/drivers/usb/Makefile | 7 + trunk/drivers/usb/atm/usbatm.c | 2 +- trunk/drivers/usb/misc/auerswald.c | 2 +- trunk/drivers/{net/usb => usb/net}/Kconfig | 0 trunk/drivers/{net/usb => usb/net}/Makefile | 0 trunk/drivers/{net/usb => usb/net}/asix.c | 0 trunk/drivers/{net/usb => usb/net}/catc.c | 0 .../drivers/{net/usb => usb/net}/cdc_ether.c | 0 .../drivers/{net/usb => usb/net}/cdc_subset.c | 0 trunk/drivers/{net/usb => usb/net}/dm9601.c | 0 trunk/drivers/{net/usb => usb/net}/gl620a.c | 0 trunk/drivers/{net/usb => usb/net}/kaweth.c | 0 trunk/drivers/{net/usb => usb/net}/kawethfw.h | 0 trunk/drivers/{net/usb => usb/net}/mcs7830.c | 0 trunk/drivers/{net/usb => usb/net}/net1080.c | 0 trunk/drivers/{net/usb => usb/net}/pegasus.c | 0 trunk/drivers/{net/usb => usb/net}/pegasus.h | 0 trunk/drivers/{net/usb => usb/net}/plusb.c | 0 .../drivers/{net/usb => usb/net}/rndis_host.c | 0 trunk/drivers/{net/usb => usb/net}/rtl8150.c | 0 trunk/drivers/{net/usb => usb/net}/usbnet.c | 0 trunk/drivers/{net/usb => usb/net}/usbnet.h | 2 +- trunk/drivers/{net/usb => usb/net}/zaurus.c | 0 trunk/drivers/usb/serial/Kconfig | 2 +- trunk/drivers/usb/serial/aircable.c | 4 +- trunk/drivers/usb/serial/io_edgeport.c | 4 +- trunk/drivers/video/Kconfig | 63 +- trunk/drivers/video/Makefile | 3 - trunk/drivers/video/arkfb.c | 1200 ----- trunk/drivers/video/atmel_lcdfb.c | 752 --- trunk/drivers/video/aty/atyfb_base.c | 3 +- trunk/drivers/video/aty/mach64_cursor.c | 1 + trunk/drivers/video/console/Kconfig | 7 + trunk/drivers/video/console/softcursor.c | 2 +- trunk/drivers/video/fbmem.c | 4 - trunk/drivers/video/i810/i810_main.c | 2 +- trunk/drivers/video/matrox/matroxfb_Ti3026.c | 2 +- trunk/drivers/video/matrox/matroxfb_accel.c | 2 +- trunk/drivers/video/matrox/matroxfb_base.c | 2 +- trunk/drivers/video/matrox/matroxfb_misc.c | 2 +- trunk/drivers/video/nvidia/nv_hw.c | 7 +- trunk/drivers/video/nvidia/nvidia.c | 2 +- trunk/drivers/video/pm2fb.c | 38 +- trunk/drivers/video/pm3fb.c | 4013 ++++++++++++++--- trunk/drivers/video/riva/rivafb-i2c.c | 2 + trunk/drivers/video/s3fb.c | 19 +- trunk/drivers/video/skeletonfb.c | 2 +- trunk/drivers/video/svgalib.c | 17 - trunk/drivers/video/vt8623fb.c | 927 ---- trunk/drivers/w1/Kconfig | 1 - trunk/fs/Kconfig | 4 + trunk/fs/Makefile | 4 - trunk/fs/affs/file.c | 6 +- trunk/fs/afs/Makefile | 3 +- trunk/fs/afs/afs.h | 23 - trunk/fs/afs/afs_fs.h | 7 +- trunk/fs/afs/callback.c | 9 +- trunk/fs/afs/dir.c | 37 +- trunk/fs/afs/file.c | 105 +- trunk/fs/afs/fsclient.c | 878 +--- trunk/fs/afs/inode.c | 74 +- trunk/fs/afs/internal.h | 101 +- trunk/fs/afs/main.c | 2 - trunk/fs/afs/misc.c | 1 - trunk/fs/afs/mntpt.c | 5 +- trunk/fs/afs/rxrpc.c | 80 +- trunk/fs/afs/security.c | 12 +- trunk/fs/afs/server.c | 3 - trunk/fs/afs/super.c | 49 +- trunk/fs/afs/vnode.c | 206 +- trunk/fs/afs/write.c | 828 ---- trunk/fs/aio.c | 35 +- trunk/fs/anon_inodes.c | 200 - trunk/fs/autofs/autofs_i.h | 4 +- trunk/fs/autofs/inode.c | 47 +- trunk/fs/autofs/root.c | 83 +- trunk/fs/autofs4/inode.c | 16 +- trunk/fs/autofs4/root.c | 18 +- trunk/fs/binfmt_misc.c | 13 +- trunk/fs/buffer.c | 58 +- trunk/fs/compat.c | 49 - trunk/fs/compat_ioctl.c | 5 +- trunk/fs/configfs/file.c | 33 +- trunk/fs/direct-io.c | 10 +- trunk/fs/eventfd.c | 228 - trunk/fs/eventpoll.c | 1206 +++-- trunk/fs/exec.c | 13 +- trunk/fs/ext3/inode.c | 12 +- trunk/fs/jbd/checkpoint.c | 2 +- trunk/fs/jbd/recovery.c | 2 +- trunk/fs/jbd/revoke.c | 2 +- trunk/fs/jbd/transaction.c | 2 +- trunk/fs/jbd2/checkpoint.c | 2 +- trunk/fs/jbd2/recovery.c | 2 +- trunk/fs/jbd2/revoke.c | 2 +- trunk/fs/jbd2/transaction.c | 2 +- trunk/fs/jffs2/histo_mips.h | 2 + trunk/fs/jffs2/readinode.c | 78 +- trunk/fs/jffs2/wbuf.c | 5 +- trunk/fs/jfs/jfs_dmap.c | 2 +- trunk/fs/jfs/jfs_imap.c | 4 +- trunk/fs/jfs/jfs_logmgr.c | 2 +- trunk/fs/libfs.c | 5 +- trunk/fs/locks.c | 5 +- trunk/fs/mpage.c | 189 +- trunk/fs/namei.c | 8 +- trunk/fs/nfs/dir.c | 37 +- trunk/fs/nfs/getroot.c | 1 + trunk/fs/nfs/idmap.c | 4 +- trunk/fs/nfs/inode.c | 3 + trunk/fs/nfs/nfs2xdr.c | 1 + trunk/fs/nfs/nfs4xdr.c | 11 +- trunk/fs/nfs/pagelist.c | 7 + trunk/fs/nfsd/Makefile | 1 + trunk/fs/nfsd/export.c | 14 +- trunk/fs/nfsd/nfs3proc.c | 2 +- trunk/fs/nfsd/nfs3xdr.c | 71 +- trunk/fs/nfsd/nfs4acl.c | 17 + trunk/fs/nfsd/nfs4state.c | 2 + trunk/fs/nfsd/nfsfh.c | 56 +- trunk/fs/nfsd/nfsproc.c | 2 +- trunk/fs/nfsd/nfsxdr.c | 53 +- trunk/fs/ocfs2/cluster/masklog.c | 5 +- trunk/fs/open.c | 3 - trunk/fs/partitions/Kconfig | 2 +- trunk/fs/partitions/efi.c | 12 +- trunk/fs/proc/base.c | 2 - trunk/fs/reiserfs/file.c | 39 +- trunk/fs/reiserfs/inode.c | 13 +- trunk/fs/reiserfs/journal.c | 4 +- trunk/fs/select.c | 4 +- trunk/fs/signalfd.c | 349 -- trunk/fs/sysfs/file.c | 33 +- trunk/fs/timerfd.c | 227 - trunk/fs/xfs/xfs_itable.c | 2 +- trunk/fs/xfs/xfs_mount.c | 3 - trunk/include/acpi/acdispat.h | 9 +- trunk/include/acpi/acglobal.h | 2 +- trunk/include/acpi/acinterp.h | 9 +- trunk/include/acpi/aclocal.h | 2 +- trunk/include/acpi/acnamesp.h | 6 +- trunk/include/acpi/acobject.h | 4 +- trunk/include/acpi/acpi_bus.h | 9 +- trunk/include/acpi/acpi_drivers.h | 6 +- trunk/include/acpi/acpi_numa.h | 2 +- trunk/include/acpi/acpiosxf.h | 3 +- trunk/include/acpi/actypes.h | 2 +- trunk/include/acpi/acutils.h | 3 +- trunk/include/acpi/platform/aclinux.h | 21 +- trunk/include/acpi/processor.h | 18 +- trunk/include/asm-alpha/poll.h | 26 +- trunk/include/asm-alpha/smp.h | 1 - trunk/include/asm-alpha/thread_info.h | 8 +- trunk/include/asm-arm/arch-at91/at91rm9200.h | 181 + trunk/include/asm-arm/arch-at91/at91sam9260.h | 9 + trunk/include/asm-arm/arch-at91/at91sam9261.h | 191 + trunk/include/asm-arm/arch-at91/at91sam9263.h | 8 + trunk/include/asm-arm/arch-at91/board.h | 2 +- trunk/include/asm-arm/arch-at91/cpu.h | 6 - trunk/include/asm-arm/arch-imx/imx-regs.h | 2 +- .../asm-arm/arch-integrator/platform.h | 2 +- trunk/include/asm-arm/arch-iop32x/glantank.h | 2 +- trunk/include/asm-arm/arch-iop32x/n2100.h | 2 +- trunk/include/asm-arm/arch-omap/aic23.h | 4 +- .../include/asm-arm/arch-omap/board-apollon.h | 9 + trunk/include/asm-arm/arch-omap/board-h4.h | 3 + trunk/include/asm-arm/arch-omap/board.h | 43 +- trunk/include/asm-arm/arch-omap/dma.h | 2 +- trunk/include/asm-arm/arch-omap/dsp.h | 250 + trunk/include/asm-arm/arch-omap/dsp_common.h | 32 +- trunk/include/asm-arm/arch-omap/gpio-switch.h | 54 - trunk/include/asm-arm/arch-omap/gpio.h | 2 +- trunk/include/asm-arm/arch-omap/gpmc.h | 2 - trunk/include/asm-arm/arch-omap/hardware.h | 9 - trunk/include/asm-arm/arch-omap/hwa742.h | 12 - trunk/include/asm-arm/arch-omap/io.h | 11 - trunk/include/asm-arm/arch-omap/irqs.h | 20 +- trunk/include/asm-arm/arch-omap/lcd_lph8923.h | 14 + trunk/include/asm-arm/arch-omap/lcd_mipid.h | 24 - trunk/include/asm-arm/arch-omap/led.h | 24 - trunk/include/asm-arm/arch-omap/mailbox.h | 73 - trunk/include/asm-arm/arch-omap/mcspi.h | 1 + trunk/include/asm-arm/arch-omap/memory.h | 13 - trunk/include/asm-arm/arch-omap/menelaus.h | 17 +- trunk/include/asm-arm/arch-omap/omap16xx.h | 12 +- trunk/include/asm-arm/arch-omap/omap24xx.h | 9 - trunk/include/asm-arm/arch-omap/omapfb.h | 188 +- trunk/include/asm-arm/arch-omap/sram.h | 3 + trunk/include/asm-arm/arch-omap/usb.h | 40 +- .../include/asm-arm/arch-s3c2410/regs-power.h | 2 +- .../asm-arm/arch-s3c2410/regs-s3c2443-clock.h | 2 +- .../asm-arm/arch-s3c2410/regs-watchdog.h | 2 +- trunk/include/asm-arm/arch-s3c2410/udc.h | 2 +- trunk/include/asm-arm/cacheflush.h | 40 +- trunk/include/asm-arm/dma-mapping.h | 2 +- trunk/include/asm-arm/glue.h | 9 - trunk/include/asm-arm/mmu_context.h | 8 +- trunk/include/asm-arm/poll.h | 28 +- trunk/include/asm-arm/proc-fns.h | 8 - trunk/include/asm-arm/system.h | 7 +- trunk/include/asm-arm26/io.h | 2 +- trunk/include/asm-arm26/memory.h | 4 +- trunk/include/asm-arm26/poll.h | 22 +- trunk/include/asm-arm26/setup.h | 2 +- trunk/include/asm-avr32/arch-at32ap/cpu.h | 33 - trunk/include/asm-avr32/poll.h | 28 +- trunk/include/asm-avr32/setup.h | 2 +- trunk/include/asm-avr32/unistd.h | 4 +- trunk/include/asm-blackfin/processor.h | 6 +- trunk/include/asm-blackfin/system.h | 4 +- trunk/include/asm-cris/poll.h | 27 +- trunk/include/asm-frv/poll.h | 18 +- trunk/include/asm-frv/tlb.h | 4 - trunk/include/asm-frv/unistd.h | 16 +- trunk/include/asm-generic/Kbuild | 1 - trunk/include/asm-generic/bitops/atomic.h | 2 +- trunk/include/asm-generic/poll.h | 37 - trunk/include/asm-h8300/poll.h | 18 +- trunk/include/asm-h8300/unistd.h | 66 +- trunk/include/asm-i386/alternative.h | 6 - trunk/include/asm-i386/bitops.h | 2 +- trunk/include/asm-i386/boot.h | 2 +- trunk/include/asm-i386/mmzone.h | 6 +- trunk/include/asm-i386/msr.h | 56 +- trunk/include/asm-i386/paravirt.h | 10 + trunk/include/asm-i386/poll.h | 28 +- trunk/include/asm-i386/smp.h | 37 +- trunk/include/asm-i386/sync_bitops.h | 2 +- trunk/include/asm-i386/thread_info.h | 2 +- trunk/include/asm-i386/tsc.h | 6 +- trunk/include/asm-i386/unistd.h | 5 +- trunk/include/asm-ia64/hw_irq.h | 1 - trunk/include/asm-ia64/iosapic.h | 2 +- trunk/include/asm-ia64/poll.h | 33 +- trunk/include/asm-ia64/smp.h | 6 +- trunk/include/asm-ia64/sn/sn_sal.h | 1 - trunk/include/asm-ia64/thread_info.h | 6 +- trunk/include/asm-ia64/tlbflush.h | 11 - trunk/include/asm-ia64/unistd.h | 5 +- trunk/include/asm-m32r/pgtable-2level.h | 4 +- trunk/include/asm-m32r/pgtable.h | 2 +- trunk/include/asm-m32r/poll.h | 33 +- trunk/include/asm-m32r/smp.h | 6 +- trunk/include/asm-m32r/system.h | 13 +- trunk/include/asm-m68k/atarihw.h | 2 +- trunk/include/asm-m68k/atariints.h | 2 +- trunk/include/asm-m68k/poll.h | 17 +- trunk/include/asm-m68k/scatterlist.h | 2 - trunk/include/asm-m68k/thread_info.h | 6 +- trunk/include/asm-mips/bootinfo.h | 2 +- trunk/include/asm-mips/poll.h | 21 +- trunk/include/asm-mips/system.h | 2 +- trunk/include/asm-parisc/compat.h | 2 +- trunk/include/asm-parisc/poll.h | 28 +- trunk/include/asm-powerpc/hw_irq.h | 11 +- trunk/include/asm-powerpc/mmu-hash64.h | 23 +- trunk/include/asm-powerpc/mmzone.h | 4 + trunk/include/asm-powerpc/paca.h | 2 +- trunk/include/asm-powerpc/page_64.h | 86 +- trunk/include/asm-powerpc/pgalloc-64.h | 31 +- trunk/include/asm-powerpc/pgtable-4k.h | 6 +- trunk/include/asm-powerpc/pgtable-64k.h | 7 +- trunk/include/asm-powerpc/poll.h | 25 +- trunk/include/asm-powerpc/ppc-pci.h | 20 +- trunk/include/asm-powerpc/ps3.h | 5 - trunk/include/asm-powerpc/qe.h | 13 +- trunk/include/asm-powerpc/reg_booke.h | 469 -- trunk/include/asm-powerpc/smp.h | 1 - trunk/include/asm-powerpc/spu_csa.h | 10 +- trunk/include/asm-powerpc/systbl.h | 1 - trunk/include/asm-powerpc/unistd.h | 3 +- trunk/include/asm-ppc/commproc.h | 13 +- trunk/include/asm-ppc/cpm2.h | 13 +- trunk/include/asm-ppc/hydra.h | 2 +- .../include/{asm-powerpc => asm-ppc}/rheap.h | 20 +- trunk/include/asm-s390/ccwdev.h | 3 +- trunk/include/asm-s390/ipl.h | 2 +- trunk/include/asm-s390/param.h | 2 +- trunk/include/asm-s390/poll.h | 36 +- trunk/include/asm-s390/smp.h | 1 - trunk/include/asm-sh/bug.h | 4 +- trunk/include/asm-sh/cpu-features.h | 1 - trunk/include/asm-sh/cpu-sh3/dma.h | 2 +- trunk/include/asm-sh/cpu-sh4/dma-sh7780.h | 2 +- trunk/include/asm-sh/cpu-sh4/dma.h | 2 +- trunk/include/asm-sh/dmabrg.h | 23 - trunk/include/asm-sh/edosk7705.h | 2 +- trunk/include/asm-sh/kdebug.h | 25 +- trunk/include/asm-sh/pgalloc.h | 44 +- trunk/include/asm-sh/poll.h | 28 +- trunk/include/asm-sh/snapgear.h | 2 +- trunk/include/asm-sh/system.h | 9 - trunk/include/asm-sh/timer.h | 25 +- trunk/include/asm-sh/unistd.h | 5 +- trunk/include/asm-sh64/poll.h | 33 +- trunk/include/asm-sparc/poll.h | 14 +- trunk/include/asm-sparc/smp.h | 1 - trunk/include/asm-sparc/unistd.h | 3 +- trunk/include/asm-sparc64/kdebug.h | 16 +- trunk/include/asm-sparc64/kprobes.h | 1 - trunk/include/asm-sparc64/openprom.h | 2 +- trunk/include/asm-sparc64/pbm.h | 152 + trunk/include/asm-sparc64/poll.h | 14 +- trunk/include/asm-sparc64/smp.h | 1 - trunk/include/asm-sparc64/unistd.h | 3 +- trunk/include/asm-um/required-features.h | 9 - trunk/include/asm-um/smp.h | 4 - trunk/include/asm-um/thread_info.h | 2 - trunk/include/asm-v850/poll.h | 17 +- trunk/include/asm-x86_64/alternative.h | 6 - trunk/include/asm-x86_64/page.h | 9 - trunk/include/asm-x86_64/poll.h | 28 +- trunk/include/asm-x86_64/smp.h | 14 +- trunk/include/asm-x86_64/system.h | 2 +- trunk/include/asm-x86_64/thread_info.h | 2 +- trunk/include/asm-x86_64/unistd.h | 9 - .../include/asm-xtensa/platform-iss/simcall.h | 2 +- trunk/include/asm-xtensa/poll.h | 20 +- trunk/include/linux/Kbuild | 3 +- trunk/include/linux/acpi.h | 3 +- trunk/include/linux/aio.h | 9 +- trunk/include/linux/aio_abi.h | 18 +- trunk/include/linux/anon_inodes.h | 16 - trunk/include/linux/blkdev.h | 2 +- trunk/include/linux/clocksource.h | 3 - trunk/include/linux/compat.h | 8 - trunk/include/linux/compiler-gcc.h | 1 - trunk/include/linux/compiler-gcc3.h | 6 +- trunk/include/linux/compiler-gcc4.h | 3 +- trunk/include/linux/compiler.h | 21 +- trunk/include/linux/crc-itu-t.h | 28 - trunk/include/linux/eventfd.h | 29 - trunk/include/linux/ext3_fs_i.h | 2 +- trunk/include/linux/ext4_fs_i.h | 2 +- trunk/include/linux/fb.h | 2 +- trunk/include/linux/firewire-cdev.h | 229 - trunk/include/linux/firewire-constants.h | 67 - trunk/include/linux/futex.h | 42 +- trunk/include/linux/generic_acl.h | 2 +- trunk/include/linux/genhd.h | 1 - trunk/include/linux/gfp.h | 6 +- trunk/include/linux/highmem.h | 27 +- trunk/include/linux/i2c-algo-bit.h | 2 +- trunk/include/linux/i2c-algo-pcf.h | 2 +- trunk/include/linux/ide.h | 93 +- trunk/include/linux/init_task.h | 34 +- trunk/include/linux/interrupt.h | 10 - trunk/include/linux/irda.h | 2 +- trunk/include/linux/kernel.h | 21 - trunk/include/linux/kthread.h | 3 - trunk/include/linux/ktime.h | 6 +- trunk/include/linux/magic.h | 1 - trunk/include/linux/mca.h | 2 - trunk/include/linux/meye.h | 2 +- trunk/include/linux/mlx4/cmd.h | 178 - trunk/include/linux/mlx4/cq.h | 123 - trunk/include/linux/mlx4/device.h | 331 -- trunk/include/linux/mlx4/doorbell.h | 97 - trunk/include/linux/mlx4/driver.h | 59 - trunk/include/linux/mlx4/qp.h | 288 -- trunk/include/linux/mlx4/srq.h | 42 - trunk/include/linux/mm_types.h | 7 +- trunk/include/linux/mmzone.h | 3 - trunk/include/linux/module.h | 5 +- trunk/include/linux/mount.h | 2 +- trunk/include/linux/mpage.h | 1 + trunk/include/linux/mtd/mtd.h | 7 + trunk/include/linux/mtd/nand.h | 16 - trunk/include/linux/mutex.h | 5 +- trunk/include/linux/netdevice.h | 2 - trunk/include/linux/netfilter/x_tables.h | 8 - .../include/linux/netfilter_arp/arp_tables.h | 41 - .../include/linux/netfilter_ipv4/ip_tables.h | 22 - .../include/linux/netfilter_ipv6/ip6_tables.h | 22 - trunk/include/linux/nfs4_acl.h | 1 + trunk/include/linux/notifier.h | 66 +- trunk/include/linux/pid.h | 5 +- trunk/include/linux/pm.h | 31 +- trunk/include/linux/pmu.h | 2 +- trunk/include/linux/radix-tree.h | 4 +- trunk/include/linux/relay.h | 3 +- trunk/include/linux/rslib.h | 4 - trunk/include/linux/sched.h | 11 +- trunk/include/linux/security.h | 2 +- trunk/include/linux/signal.h | 126 - trunk/include/linux/signalfd.h | 97 - trunk/include/linux/smp.h | 1 + trunk/include/linux/sonypi.h | 2 +- trunk/include/linux/sunrpc/svc.h | 19 - trunk/include/linux/sunrpc/svcsock.h | 3 +- trunk/include/linux/suspend.h | 35 +- trunk/include/linux/svga.h | 2 - trunk/include/linux/synclink.h | 24 - trunk/include/linux/syscalls.h | 6 - trunk/include/linux/task_io_accounting_ops.h | 28 - trunk/include/linux/tifm.h | 1 - trunk/include/linux/timerfd.h | 17 - trunk/include/linux/tty_driver.h | 9 - trunk/include/linux/tty_ldisc.h | 7 - trunk/include/linux/usb.h | 2 +- trunk/include/linux/vmstat.h | 3 + trunk/include/linux/workqueue.h | 95 +- trunk/include/linux/writeback.h | 10 +- trunk/include/net/ieee80211.h | 2 - trunk/include/net/irda/af_irda.h | 2 +- trunk/include/net/irda/irda.h | 2 +- trunk/include/net/irda/iriap.h | 2 +- trunk/include/net/irda/iriap_event.h | 2 +- trunk/include/net/irda/irias_object.h | 2 +- trunk/include/net/irda/irlan_client.h | 2 +- trunk/include/net/irda/irlan_common.h | 2 +- trunk/include/net/irda/irlan_eth.h | 2 +- trunk/include/net/irda/irlan_event.h | 2 +- trunk/include/net/irda/irlan_filter.h | 2 +- trunk/include/net/irda/irlan_provider.h | 2 +- trunk/include/net/irda/irlap.h | 2 +- trunk/include/net/irda/irlmp.h | 2 +- trunk/include/net/irda/irlmp_event.h | 2 +- trunk/include/net/irda/irlmp_frame.h | 2 +- trunk/include/net/irda/irmod.h | 2 +- trunk/include/net/irda/irqueue.h | 2 +- trunk/include/net/irda/irttp.h | 2 +- trunk/include/net/irda/parameters.h | 2 +- trunk/include/net/irda/timer.h | 2 +- trunk/include/net/irda/wrapper.h | 2 +- trunk/include/net/netfilter/nf_conntrack.h | 7 + .../net/netfilter/nf_conntrack_l3proto.h | 3 + trunk/include/net/netfilter/nf_nat_rule.h | 11 +- trunk/include/net/udp.h | 9 +- trunk/include/net/udplite.h | 2 +- trunk/include/rdma/ib_umem.h | 81 - trunk/include/rdma/ib_verbs.h | 28 +- trunk/include/scsi/libsas.h | 3 +- trunk/include/video/atmel_lcdc.h | 196 - trunk/include/video/pm3fb.h | 110 + trunk/init/Kconfig | 71 +- trunk/init/do_mounts.c | 7 +- trunk/init/main.c | 6 - trunk/kernel/Kconfig.preempt | 4 +- trunk/kernel/compat.c | 8 +- trunk/kernel/configs.c | 15 +- trunk/kernel/cpu.c | 66 +- trunk/kernel/cpuset.c | 7 +- trunk/kernel/exit.c | 40 +- trunk/kernel/fork.c | 28 +- trunk/kernel/futex.c | 988 +--- trunk/kernel/futex_compat.c | 22 +- trunk/kernel/hrtimer.c | 2 - trunk/kernel/irq/handle.c | 1 + trunk/kernel/kmod.c | 6 + trunk/kernel/kthread.c | 113 +- trunk/kernel/module.c | 10 +- trunk/kernel/mutex.c | 8 +- trunk/kernel/pid.c | 11 +- trunk/kernel/power/disk.c | 195 +- trunk/kernel/power/main.c | 42 +- trunk/kernel/power/power.h | 7 +- trunk/kernel/power/snapshot.c | 14 +- trunk/kernel/power/user.c | 13 +- trunk/kernel/profile.c | 4 - trunk/kernel/rcupdate.c | 2 - trunk/kernel/relay.c | 37 +- trunk/kernel/rtmutex.c | 41 +- trunk/kernel/rtmutex_common.h | 34 - trunk/kernel/sched.c | 72 +- trunk/kernel/signal.c | 162 +- trunk/kernel/softirq.c | 4 - trunk/kernel/softlockup.c | 4 - trunk/kernel/stop_machine.c | 4 - trunk/kernel/sys.c | 112 +- trunk/kernel/sys_ni.c | 5 - trunk/kernel/sysctl.c | 12 - trunk/kernel/time/clocksource.c | 51 +- trunk/kernel/time/timer_list.c | 25 +- trunk/kernel/timer.c | 4 - trunk/kernel/wait.c | 2 +- trunk/kernel/workqueue.c | 783 ++-- trunk/lib/Kconfig | 8 - trunk/lib/Makefile | 3 +- trunk/lib/crc-itu-t.c | 69 - trunk/lib/hexdump.c | 104 - trunk/lib/radix-tree.c | 2 +- trunk/lib/reed_solomon/reed_solomon.c | 84 +- trunk/mm/Kconfig | 2 +- trunk/mm/filemap.c | 8 +- trunk/mm/filemap_xip.c | 7 +- trunk/mm/hugetlb.c | 33 - trunk/mm/mmap.c | 2 +- trunk/mm/page-writeback.c | 59 +- trunk/mm/page_alloc.c | 52 +- trunk/mm/slab.c | 41 +- trunk/mm/slub.c | 1201 +++-- trunk/mm/swap.c | 2 +- trunk/mm/thrash.c | 5 +- trunk/mm/truncate.c | 3 +- trunk/mm/vmscan.c | 2 +- trunk/mm/vmstat.c | 95 +- trunk/net/Kconfig | 1 - trunk/net/ax25/Kconfig | 2 +- trunk/net/bluetooth/Kconfig | 2 +- trunk/net/bluetooth/hidp/core.c | 10 +- trunk/net/core/dev.c | 2 +- trunk/net/core/flow.c | 2 +- trunk/net/core/link_watch.c | 166 +- trunk/net/decnet/af_decnet.c | 2 +- trunk/net/ieee80211/ieee80211_geo.c | 16 - trunk/net/ieee80211/ieee80211_wx.c | 8 +- trunk/net/ipv4/Kconfig | 4 +- trunk/net/ipv4/cipso_ipv4.c | 2 +- trunk/net/ipv4/ipvs/ip_vs_ctl.c | 1 - trunk/net/ipv4/ipvs/ip_vs_sed.c | 2 +- trunk/net/ipv4/netfilter/arptable_filter.c | 140 +- trunk/net/ipv4/netfilter/iptable_filter.c | 73 +- trunk/net/ipv4/netfilter/iptable_mangle.c | 99 +- trunk/net/ipv4/netfilter/iptable_raw.c | 79 +- trunk/net/ipv4/netfilter/nf_nat_rule.c | 86 +- trunk/net/ipv4/netfilter/nf_nat_standalone.c | 11 +- trunk/net/ipv4/udp.c | 87 +- trunk/net/ipv4/udp_impl.h | 6 +- trunk/net/ipv4/udplite.c | 7 +- trunk/net/ipv6/addrconf.c | 4 - trunk/net/ipv6/exthdrs.c | 16 +- trunk/net/ipv6/ip6_output.c | 13 +- trunk/net/ipv6/netfilter/Kconfig | 2 +- trunk/net/ipv6/netfilter/ip6table_filter.c | 70 +- trunk/net/ipv6/netfilter/ip6table_mangle.c | 96 +- trunk/net/ipv6/netfilter/ip6table_raw.c | 52 +- trunk/net/ipv6/udp.c | 21 +- trunk/net/ipv6/udp_impl.h | 2 - trunk/net/ipv6/udplite.c | 2 +- trunk/net/irda/Kconfig | 2 +- trunk/net/iucv/iucv.c | 6 - trunk/net/llc/af_llc.c | 2 +- trunk/net/mac80211/ieee80211_sta.c | 2 +- trunk/net/netfilter/Kconfig | 2 +- trunk/net/netfilter/nf_conntrack_core.c | 14 +- trunk/net/netfilter/nf_conntrack_expect.c | 2 +- trunk/net/netfilter/nf_conntrack_netlink.c | 40 +- trunk/net/netfilter/xt_conntrack.c | 54 - trunk/net/rxrpc/ar-peer.c | 4 +- trunk/net/sched/sch_generic.c | 41 +- trunk/net/sched/sch_teql.c | 5 +- trunk/net/sctp/chunk.c | 2 +- trunk/net/sctp/socket.c | 23 +- trunk/net/sctp/ulpevent.c | 11 +- trunk/net/sunrpc/auth_gss/svcauth_gss.c | 15 +- trunk/net/sunrpc/rpc_pipe.c | 9 +- trunk/net/sunrpc/sched.c | 26 +- trunk/net/sunrpc/sunrpc_syms.c | 6 +- trunk/net/sunrpc/svc.c | 2 +- trunk/net/sunrpc/svcauth.c | 2 +- trunk/net/sunrpc/svcauth_unix.c | 10 +- trunk/net/sunrpc/svcsock.c | 34 +- trunk/scripts/basic/docproc.c | 2 +- trunk/scripts/kernel-doc | 7 +- trunk/scripts/mod/modpost.c | 1 - trunk/security/selinux/Kconfig | 2 +- trunk/sound/Kconfig | 1 - trunk/sound/core/Kconfig | 2 +- trunk/sound/oss/es1371.c | 2 +- trunk/sound/oss/pas2_pcm.c | 2 +- trunk/sound/oss/trident.c | 4 +- trunk/sound/pci/ac97/ac97_codec.c | 2 +- trunk/sound/pci/ice1712/delta.h | 4 +- trunk/sound/pci/mixart/mixart.c | 2 +- trunk/sound/soc/pxa/pxa2xx-ac97.h | 2 +- trunk/sound/soc/pxa/pxa2xx-i2s.h | 2 +- trunk/sound/sparc/dbri.c | 2 +- 1419 files changed, 25482 insertions(+), 50702 deletions(-) delete mode 100644 trunk/Documentation/device-mapper/delay.txt delete mode 100644 trunk/Documentation/fb/arkfb.txt delete mode 100644 trunk/Documentation/fb/vt8623fb.txt delete mode 100644 trunk/arch/arm/mach-omap1/mailbox.c delete mode 100644 trunk/arch/arm/mach-omap2/mailbox.c delete mode 100644 trunk/arch/arm/mm/abort-ev7.S delete mode 100644 trunk/arch/arm/mm/cache-v7.S delete mode 100644 trunk/arch/arm/mm/proc-v7.S delete mode 100644 trunk/arch/arm/plat-omap/debug-leds.c delete mode 100644 trunk/arch/arm/plat-omap/mailbox.c delete mode 100644 trunk/arch/arm/plat-omap/mailbox.h delete mode 100644 trunk/arch/powerpc/mm/slice.c delete mode 100644 trunk/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c create mode 100644 trunk/arch/ppc/lib/rheap.c delete mode 100644 trunk/arch/sh/drivers/dma/dmabrg.c delete mode 100644 trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c create mode 100644 trunk/arch/sh/kernel/cpu/sh4/ex.S create mode 100644 trunk/arch/um/Kconfig.scsi delete mode 100644 trunk/drivers/char/hw_random/pasemi-rng.c create mode 100644 trunk/drivers/char/watchdog/i8xx_tco.c create mode 100644 trunk/drivers/char/watchdog/i8xx_tco.h delete mode 100644 trunk/drivers/char/watchdog/mtx-1_wdt.c delete mode 100644 trunk/drivers/firewire/Kconfig delete mode 100644 trunk/drivers/firewire/Makefile delete mode 100644 trunk/drivers/firewire/fw-card.c delete mode 100644 trunk/drivers/firewire/fw-cdev.c delete mode 100644 trunk/drivers/firewire/fw-device.c delete mode 100644 trunk/drivers/firewire/fw-device.h delete mode 100644 trunk/drivers/firewire/fw-iso.c delete mode 100644 trunk/drivers/firewire/fw-ohci.c delete mode 100644 trunk/drivers/firewire/fw-ohci.h delete mode 100644 trunk/drivers/firewire/fw-sbp2.c delete mode 100644 trunk/drivers/firewire/fw-topology.c delete mode 100644 trunk/drivers/firewire/fw-topology.h delete mode 100644 trunk/drivers/firewire/fw-transaction.c delete mode 100644 trunk/drivers/firewire/fw-transaction.h rename trunk/drivers/infiniband/core/{umem.c => uverbs_mem.c} (59%) delete mode 100644 trunk/drivers/infiniband/hw/mlx4/Kconfig delete mode 100644 trunk/drivers/infiniband/hw/mlx4/Makefile delete mode 100644 trunk/drivers/infiniband/hw/mlx4/ah.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/cq.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/doorbell.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/mad.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/main.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h delete mode 100644 trunk/drivers/infiniband/hw/mlx4/mr.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/qp.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/srq.c delete mode 100644 trunk/drivers/infiniband/hw/mlx4/user.h delete mode 100644 trunk/drivers/md/dm-delay.c create mode 100644 trunk/drivers/mtd/chips/amd_flash.c create mode 100644 trunk/drivers/mtd/chips/jedec.c create mode 100644 trunk/drivers/mtd/chips/sharp.c create mode 100644 trunk/drivers/mtd/maps/arctic-mtd.c create mode 100644 trunk/drivers/mtd/maps/beech-mtd.c rename trunk/drivers/mtd/nand/{cafe_nand.c => cafe.c} (88%) create mode 100644 trunk/drivers/mtd/nand/cafe_ecc.c delete mode 100644 trunk/drivers/mtd/nand/plat_nand.c delete mode 100644 trunk/drivers/net/irda/kingsun-sir.c delete mode 100644 trunk/drivers/net/mlx4/Makefile delete mode 100644 trunk/drivers/net/mlx4/alloc.c delete mode 100644 trunk/drivers/net/mlx4/catas.c delete mode 100644 trunk/drivers/net/mlx4/cmd.c delete mode 100644 trunk/drivers/net/mlx4/cq.c delete mode 100644 trunk/drivers/net/mlx4/eq.c delete mode 100644 trunk/drivers/net/mlx4/fw.c delete mode 100644 trunk/drivers/net/mlx4/fw.h delete mode 100644 trunk/drivers/net/mlx4/icm.c delete mode 100644 trunk/drivers/net/mlx4/icm.h delete mode 100644 trunk/drivers/net/mlx4/intf.c delete mode 100644 trunk/drivers/net/mlx4/main.c delete mode 100644 trunk/drivers/net/mlx4/mcg.c delete mode 100644 trunk/drivers/net/mlx4/mlx4.h delete mode 100644 trunk/drivers/net/mlx4/mr.c delete mode 100644 trunk/drivers/net/mlx4/pd.c delete mode 100644 trunk/drivers/net/mlx4/profile.c delete mode 100644 trunk/drivers/net/mlx4/qp.c delete mode 100644 trunk/drivers/net/mlx4/reset.c delete mode 100644 trunk/drivers/net/mlx4/srq.c rename trunk/drivers/s390/{char => }/Kconfig (59%) delete mode 100644 trunk/drivers/spi/mpc52xx_psc_spi.c rename trunk/drivers/{net/usb => usb/net}/Kconfig (100%) rename trunk/drivers/{net/usb => usb/net}/Makefile (100%) rename trunk/drivers/{net/usb => usb/net}/asix.c (100%) rename trunk/drivers/{net/usb => usb/net}/catc.c (100%) rename trunk/drivers/{net/usb => usb/net}/cdc_ether.c (100%) rename trunk/drivers/{net/usb => usb/net}/cdc_subset.c (100%) rename trunk/drivers/{net/usb => usb/net}/dm9601.c (100%) rename trunk/drivers/{net/usb => usb/net}/gl620a.c (100%) rename trunk/drivers/{net/usb => usb/net}/kaweth.c (100%) rename trunk/drivers/{net/usb => usb/net}/kawethfw.h (100%) rename trunk/drivers/{net/usb => usb/net}/mcs7830.c (100%) rename trunk/drivers/{net/usb => usb/net}/net1080.c (100%) rename trunk/drivers/{net/usb => usb/net}/pegasus.c (100%) rename trunk/drivers/{net/usb => usb/net}/pegasus.h (100%) rename trunk/drivers/{net/usb => usb/net}/plusb.c (100%) rename trunk/drivers/{net/usb => usb/net}/rndis_host.c (100%) rename trunk/drivers/{net/usb => usb/net}/rtl8150.c (100%) rename trunk/drivers/{net/usb => usb/net}/usbnet.c (100%) rename trunk/drivers/{net/usb => usb/net}/usbnet.h (99%) rename trunk/drivers/{net/usb => usb/net}/zaurus.c (100%) delete mode 100644 trunk/drivers/video/arkfb.c delete mode 100644 trunk/drivers/video/atmel_lcdfb.c delete mode 100644 trunk/drivers/video/vt8623fb.c delete mode 100644 trunk/fs/afs/write.c delete mode 100644 trunk/fs/anon_inodes.c delete mode 100644 trunk/fs/eventfd.c create mode 100644 trunk/fs/jffs2/histo_mips.h delete mode 100644 trunk/fs/signalfd.c delete mode 100644 trunk/fs/timerfd.c create mode 100644 trunk/include/asm-arm/arch-omap/dsp.h delete mode 100644 trunk/include/asm-arm/arch-omap/gpio-switch.h delete mode 100644 trunk/include/asm-arm/arch-omap/hwa742.h create mode 100644 trunk/include/asm-arm/arch-omap/lcd_lph8923.h delete mode 100644 trunk/include/asm-arm/arch-omap/lcd_mipid.h delete mode 100644 trunk/include/asm-arm/arch-omap/led.h delete mode 100644 trunk/include/asm-arm/arch-omap/mailbox.h delete mode 100644 trunk/include/asm-avr32/arch-at32ap/cpu.h delete mode 100644 trunk/include/asm-generic/poll.h delete mode 100644 trunk/include/asm-powerpc/reg_booke.h rename trunk/include/{asm-powerpc => asm-ppc}/rheap.h (75%) delete mode 100644 trunk/include/asm-sh/dmabrg.h create mode 100644 trunk/include/asm-sparc64/pbm.h delete mode 100644 trunk/include/asm-um/required-features.h delete mode 100644 trunk/include/linux/anon_inodes.h delete mode 100644 trunk/include/linux/crc-itu-t.h delete mode 100644 trunk/include/linux/eventfd.h delete mode 100644 trunk/include/linux/firewire-cdev.h delete mode 100644 trunk/include/linux/firewire-constants.h delete mode 100644 trunk/include/linux/mlx4/cmd.h delete mode 100644 trunk/include/linux/mlx4/cq.h delete mode 100644 trunk/include/linux/mlx4/device.h delete mode 100644 trunk/include/linux/mlx4/doorbell.h delete mode 100644 trunk/include/linux/mlx4/driver.h delete mode 100644 trunk/include/linux/mlx4/qp.h delete mode 100644 trunk/include/linux/mlx4/srq.h delete mode 100644 trunk/include/linux/signalfd.h delete mode 100644 trunk/include/linux/timerfd.h delete mode 100644 trunk/include/rdma/ib_umem.h delete mode 100644 trunk/include/video/atmel_lcdc.h delete mode 100644 trunk/lib/crc-itu-t.c delete mode 100644 trunk/lib/hexdump.c diff --git a/[refs] b/[refs] index de8db9024438..2c570f031ef2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ee54d2d87a8158d14434c1a3274bd7f713105836 +refs/heads/master: 529fa5473123a9e81e711a92e46fba732c4264ed diff --git a/trunk/CREDITS b/trunk/CREDITS index 6829e91a88d4..80e241304b8e 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -380,7 +380,7 @@ S: FutureTV Labs Ltd S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG S: United Kingdom -N: Thomas Bogendörfer +N: Thomas Bogendörfer E: tsbogend@alpha.franken.de D: PCnet32 driver, SONIC driver, JAZZ_ESP driver D: newport abscon driver, g364 framebuffer driver @@ -400,7 +400,7 @@ W: http://math-www.uni-paderborn.de/~axel/ D: Configuration help text support D: Linux CD and Support Giveaway List -N: Erik Inge Bolsø +N: Erik Inge Bolsø E: knan@mo.himolde.no D: Misc kernel hacks @@ -428,7 +428,7 @@ D: Various fixes (mostly networking) S: Montreal, Quebec S: Canada -N: Zoltán Böszörményi +N: Zoltán Böszörményi E: zboszor@mail.externet.hu D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support @@ -1029,11 +1029,11 @@ D: Future Domain TMC-16x0 SCSI driver (author) D: APM driver (early port) D: DRM drivers (author of several) -N: János Farkas +N: János Farkas E: chexum@shadow.banki.hu D: romfs, various (mostly networking) fixes P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71 6D 9C F3 9F F2 BF DF 6E -S: Madarász Viktor utca 25 +S: Madarász Viktor utca 25 S: 1131 Budapest S: Hungary @@ -1044,10 +1044,10 @@ D: UDF filesystem S: (ask for current address) S: USA -N: Jürgen Fischer -E: fischer@norbit.de +N: Jürgen Fischer +E: fischer@norbit.de (=?iso-8859-1?q?J=FCrgen?= Fischer) D: Author of Adaptec AHA-152x SCSI driver -S: Schulstraße 18 +S: Schulstraße 18 S: 26506 Norden S: Germany @@ -1113,7 +1113,7 @@ E: fuganti@netbank.com.br D: random kernel hacker, ZF MachZ Watchdog driver S: Conectiva S.A. S: R. Tocantins, 89 - Cristo Rei -S: 80050-430 - Curitiba - Paraná +S: 80050-430 - Curitiba - Paraná S: Brazil N: Kumar Gala @@ -1258,12 +1258,12 @@ S: 44 St. Joseph Street, Suite 506 S: Toronto, Ontario, M4Y 2W4 S: Canada -N: Richard Günther +N: Richard Günther E: rguenth@tat.physik.uni-tuebingen.de W: http://www.tat.physik.uni-tuebingen.de/~rguenth P: 2048/2E829319 2F 83 FC 93 E9 E4 19 E2 93 7A 32 42 45 37 23 57 D: binfmt_misc -S: 72074 Tübingen +S: 72074 Tübingen S: Germany N: Justin Guyett @@ -1287,7 +1287,7 @@ N: Bruno Haible E: haible@ma2s2.mathematik.uni-karlsruhe.de D: SysV FS, shm swapping, memory management fixes S: 17 rue Danton -S: F - 94270 Le Kremlin-Bicêtre +S: F - 94270 Le Kremlin-Bicêtre S: France N: Greg Hankins @@ -1701,7 +1701,7 @@ S: Czech Republic N: Jakob Kemi E: jakob.kemi@telia.com D: V4L W9966 Webcam driver -S: Forsbyvägen 33 +S: Forsbyvägen 33 S: 74143 Knivsta S: Sweden @@ -2065,7 +2065,7 @@ D: misc. kernel hacking and debugging S: Cambridge, MA 02139 S: USA -N: Martin von Löwis +N: Martin von Löwis E: loewis@informatik.hu-berlin.de D: script binary format D: NTFS driver @@ -2142,7 +2142,7 @@ S: PO BOX 220, HFX. CENTRAL S: Halifax, Nova Scotia S: Canada B3J 3C8 -N: Kai Mäkisara +N: Kai Mäkisara E: Kai.Makisara@kolumbus.fi D: SCSI Tape Driver @@ -2785,10 +2785,10 @@ N: Juan Quintela E: quintela@fi.udc.es D: Memory Management hacking S: LFCIA -S: Departamento de Computación -S: Universidade da Coruña +S: Departamento de Computación +S: Universidade da Coruña S: E-15071 -S: A Coruña +S: A Coruña S: Spain N: Augusto Cesar Radtke @@ -2939,7 +2939,7 @@ E: aris@cathedrallabs.org D: Support for EtherExpress 10 ISA (i82595) in eepro driver D: User level driver support for input S: R. Jose Serrato, 130 - Santa Candida -S: 82640-320 - Curitiba - Paraná +S: 82640-320 - Curitiba - Paraná S: Brazil N: Alessandro Rubini @@ -3345,15 +3345,15 @@ P: 1024D/D0FE7AFB B24A 65C9 1D71 2AC2 DE87 CA26 189B 9946 D0FE 7AFB D: rcutorture maintainer D: lock annotations, finding and fixing lock bugs -N: Winfried Trümper +N: Winfried Trümper E: winni@xpilot.org W: http://www.shop.de/~winni/ D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages) D: CD-Writing HOWTO, various mini-HOWTOs D: One-week tutorials on Linux twice a year (free of charge) -D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests +D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests S: Tacitusstr. 6 -S: D-50968 Köln +S: D-50968 Köln N: Tsu-Sheng Tsao E: tsusheng@scf.usc.edu diff --git a/trunk/Documentation/ABI/removed/devfs b/trunk/Documentation/ABI/removed/devfs index 8ffd28bf6598..8195c4e0d0a1 100644 --- a/trunk/Documentation/ABI/removed/devfs +++ b/trunk/Documentation/ABI/removed/devfs @@ -6,7 +6,7 @@ Description: races, contains a naming policy within the kernel that is against the LSB, and can be replaced by using udev. The files fs/devfs/*, include/linux/devfs_fs*.h were removed, - along with the assorted devfs function calls throughout the + along with the the assorted devfs function calls throughout the kernel tree. Users: diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 38f88b6ae405..a2b2b4d187c5 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -84,10 +84,6 @@ X!Iinclude/linux/kobject.h !Ekernel/rcupdate.c - Device Resource Management -!Edrivers/base/devres.c - - diff --git a/trunk/Documentation/MSI-HOWTO.txt b/trunk/Documentation/MSI-HOWTO.txt index 0d8240774fca..d389388c733e 100644 --- a/trunk/Documentation/MSI-HOWTO.txt +++ b/trunk/Documentation/MSI-HOWTO.txt @@ -480,8 +480,8 @@ The PCI stack provides 3 possible levels of MSI disabling: 6.1. Disabling MSI on a single device -Under some circumstances it might be required to disable MSI on a -single device. This may be achieved by either not calling pci_enable_msi() +Under some circumstances, it might be required to disable MSI on a +single device, It may be achived by either not calling pci_enable_msi() or all, or setting the pci_dev->no_msi flag before (most of the time in a quirk). @@ -492,7 +492,7 @@ being able to route MSI between busses. In this case, MSI have to be disabled on all devices behind this bridge. It is achieves by setting the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge subordinate bus. There is no need to set the same flag on bridges that -are below the broken bridge. When pci_enable_msi() is called to enable +are below the broken brigde. When pci_enable_msi() is called to enable MSI on a device, pci_msi_supported() takes care of checking the NO_MSI flag in all parent busses of the device. diff --git a/trunk/Documentation/SubmitChecklist b/trunk/Documentation/SubmitChecklist index 3af3e65cf43b..bd23dc0bc0c7 100644 --- a/trunk/Documentation/SubmitChecklist +++ b/trunk/Documentation/SubmitChecklist @@ -73,14 +73,10 @@ kernel patches. If the new code is substantial, addition of subsystem-specific fault injection might be appropriate. -22: Newly-added code has been compiled with `gcc -W' (use "make - EXTRA_CFLAGS=-W"). This will generate lots of noise, but is good for - finding bugs like "warning: comparison between signed and unsigned". +22: Newly-added code has been compiled with `gcc -W'. This will generate + lots of noise, but is good for finding bugs like "warning: comparison + between signed and unsigned". 23: Tested after it has been merged into the -mm patchset to make sure that it still works with all of the other queued patches and various changes in the VM, VFS, and other subsystems. - -24: Avoid whitespace damage such as indenting with spaces or whitespace - at the end of lines. You can test this by feeding the patch to - "git apply --check --whitespace=error-all" diff --git a/trunk/Documentation/SubmittingPatches b/trunk/Documentation/SubmittingPatches index a417b25fb1aa..b0d0043f7c46 100644 --- a/trunk/Documentation/SubmittingPatches +++ b/trunk/Documentation/SubmittingPatches @@ -363,8 +363,7 @@ area or subsystem of the kernel is being patched. The "summary phrase" in the email's Subject should concisely describe the patch which that email contains. The "summary phrase" should not be a filename. Do not use the same "summary -phrase" for every patch in a whole patch series (where a "patch -series" is an ordered sequence of multiple, related patches). +phrase" for every patch in a whole patch series. Bear in mind that the "summary phrase" of your email becomes a globally-unique identifier for that patch. It propagates diff --git a/trunk/Documentation/arm/Interrupts b/trunk/Documentation/arm/Interrupts index 0d3dbf1099bc..72c93de8cd4e 100644 --- a/trunk/Documentation/arm/Interrupts +++ b/trunk/Documentation/arm/Interrupts @@ -149,7 +149,7 @@ So, what's changed? 3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type. -4. Direct access to SA1111 INTPOL is deprecated. Use set_irq_type instead. +4. Direct access to SA1111 INTPOL is depreciated. Use set_irq_type instead. 5. A handler is expected to perform any necessary acknowledgement of the parent IRQ via the correct chip specific function. For instance, if diff --git a/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt b/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt index f4a7b22c8664..d6b1de92b111 100644 --- a/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt +++ b/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt @@ -23,7 +23,7 @@ Support http://handhelds.org/moin/moin.cgi/HpIpaqH1940 - Herbert Pötzl pages: + Herbert Pötzl pages: http://vserver.13thfloor.at/H1940/ @@ -32,7 +32,7 @@ Maintainers ----------- This project is being maintained and developed by a variety - of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl. + of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl. Thanks to the many others who have also provided support. diff --git a/trunk/Documentation/auxdisplay/cfag12864b b/trunk/Documentation/auxdisplay/cfag12864b index b714183d4125..3572b98f45b8 100644 --- a/trunk/Documentation/auxdisplay/cfag12864b +++ b/trunk/Documentation/auxdisplay/cfag12864b @@ -78,9 +78,9 @@ Select (17)------------------------------(16) Data / Instruction Ground (18)---[GND] [+5v]---(19) LED + Ground (19)---[GND] Ground (20)---[GND] E A Values: -Ground (21)---[GND] [GND]---[P1]---(18) Vee - R = Resistor = 22 ohm -Ground (22)---[GND] | - P1 = Preset = 10 Kohm -Ground (23)---[GND] ---- S ------( 3) V0 - P2 = Preset = 1 Kohm +Ground (21)---[GND] [GND]---[P1]---(18) Vee · R = Resistor = 22 ohm +Ground (22)---[GND] | · P1 = Preset = 10 Kohm +Ground (23)---[GND] ---- S ------( 3) V0 · P2 = Preset = 1 Kohm Ground (24)---[GND] | | Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED - diff --git a/trunk/Documentation/binfmt_misc.txt b/trunk/Documentation/binfmt_misc.txt index f609ebf9c78f..d097f09ee15a 100644 --- a/trunk/Documentation/binfmt_misc.txt +++ b/trunk/Documentation/binfmt_misc.txt @@ -113,4 +113,4 @@ cause unexpected behaviour and can be a security hazard. There is a web page about binfmt_misc at http://www.tat.physik.uni-tuebingen.de/~rguenth/linux/binfmt_misc.html -Richard Günther +Richard Günther diff --git a/trunk/Documentation/block/ioprio.txt b/trunk/Documentation/block/ioprio.txt index 1b930ef5a079..96ccf681075e 100644 --- a/trunk/Documentation/block/ioprio.txt +++ b/trunk/Documentation/block/ioprio.txt @@ -6,10 +6,10 @@ Intro ----- With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io -priorities are supported for reads on files. This enables users to io nice -processes or process groups, similar to what has been possible with cpu -scheduling for ages. This document mainly details the current possibilities -with cfq; other io schedulers do not support io priorities thus far. +priorities is supported for reads on files. This enables users to io nice +processes or process groups, similar to what has been possible to cpu +scheduling for ages. This document mainly details the current possibilites +with cfq, other io schedulers do not support io priorities so far. Scheduling classes ------------------ diff --git a/trunk/Documentation/cpu-freq/cpufreq-stats.txt b/trunk/Documentation/cpu-freq/cpufreq-stats.txt index fc647492e940..53d62c1e1c94 100644 --- a/trunk/Documentation/cpu-freq/cpufreq-stats.txt +++ b/trunk/Documentation/cpu-freq/cpufreq-stats.txt @@ -17,7 +17,7 @@ Contents 1. Introduction -cpufreq-stats is a driver that provides CPU frequency statistics for each CPU. +cpufreq-stats is a driver that provices CPU frequency statistics for each CPU. These statistics are provided in /sysfs as a bunch of read_only interfaces. This interface (when configured) will appear in a separate directory under cpufreq in /sysfs (/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU. diff --git a/trunk/Documentation/cpu-hotplug.txt b/trunk/Documentation/cpu-hotplug.txt index b6d24c22274b..cc60d29b954c 100644 --- a/trunk/Documentation/cpu-hotplug.txt +++ b/trunk/Documentation/cpu-hotplug.txt @@ -217,17 +217,14 @@ Q: What happens when a CPU is being logically offlined? A: The following happen, listed in no particular order :-) - A notification is sent to in-kernel registered modules by sending an event - CPU_DOWN_PREPARE or CPU_DOWN_PREPARE_FROZEN, depending on whether or not the - CPU is being offlined while tasks are frozen due to a suspend operation in - progress + CPU_DOWN_PREPARE - All process is migrated away from this outgoing CPU to a new CPU - All interrupts targeted to this CPU is migrated to a new CPU - timers/bottom half/task lets are also migrated to a new CPU - Once all services are migrated, kernel calls an arch specific routine __cpu_disable() to perform arch specific cleanup. - Once this is successful, an event for successful cleanup is sent by an event - CPU_DEAD (or CPU_DEAD_FROZEN if tasks are frozen due to a suspend while the - CPU is being offlined). + CPU_DEAD. "It is expected that each service cleans up when the CPU_DOWN_PREPARE notifier is called, when CPU_DEAD is called its expected there is nothing @@ -245,11 +242,9 @@ A: This is what you would need in your kernel code to receive notifications. switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: foobar_online_action(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: foobar_dead_action(cpu); break; } diff --git a/trunk/Documentation/crypto/api-intro.txt b/trunk/Documentation/crypto/api-intro.txt index a2ac6d294793..9b84b805ab75 100644 --- a/trunk/Documentation/crypto/api-intro.txt +++ b/trunk/Documentation/crypto/api-intro.txt @@ -177,7 +177,7 @@ Portions of this API were derived from the following projects: and; Nettle (http://www.lysator.liu.se/~nisse/nettle/) - Niels Möller + Niels Möller Original developers of the crypto algorithms: @@ -200,8 +200,8 @@ SHA1 algorithm contributors: DES algorithm contributors: Raimar Falke - Gisle Sælensminde - Niels Möller + Gisle Sælensminde + Niels Möller Blowfish algorithm contributors: Herbert Valerio Riedel diff --git a/trunk/Documentation/device-mapper/delay.txt b/trunk/Documentation/device-mapper/delay.txt deleted file mode 100644 index 15adc55359e5..000000000000 --- a/trunk/Documentation/device-mapper/delay.txt +++ /dev/null @@ -1,26 +0,0 @@ -dm-delay -======== - -Device-Mapper's "delay" target delays reads and/or writes -and maps them to different devices. - -Parameters: - [ ] - -With separate write parameters, the first set is only used for reads. -Delays are specified in milliseconds. - -Example scripts -=============== -[[ -#!/bin/sh -# Create device delaying rw operation for 500ms -echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed -]] - -[[ -#!/bin/sh -# Create device delaying only write operation for 500ms and -# splitting reads and writes to different devices $1 $2 -echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed -]] diff --git a/trunk/Documentation/driver-model/platform.txt b/trunk/Documentation/driver-model/platform.txt index 19c4a6e13676..f7c9262b2dc8 100644 --- a/trunk/Documentation/driver-model/platform.txt +++ b/trunk/Documentation/driver-model/platform.txt @@ -16,7 +16,7 @@ host bridges to peripheral buses, and most controllers integrated into system-on-chip platforms. What they usually have in common is direct addressing from a CPU bus. Rarely, a platform_device will be connected through a segment of some other kind of bus; but its -registers will still be directly addressable. +registers will still be directly addressible. Platform devices are given a name, used in driver binding, and a list of resources such as addresses and IRQs. @@ -125,7 +125,7 @@ three different ways to find such a match: usually register later during booting, or by module loading. - Registering a driver using platform_driver_probe() works just like - using platform_driver_register(), except that the driver won't + using platform_driver_register(), except that the the driver won't be probed later if another device registers. (Which is OK, since this interface is only for use with non-hotpluggable devices.) diff --git a/trunk/Documentation/dvb/README.dvb-usb b/trunk/Documentation/dvb/README.dvb-usb index bf2a9cdfe7bb..46b78b7331c2 100644 --- a/trunk/Documentation/dvb/README.dvb-usb +++ b/trunk/Documentation/dvb/README.dvb-usb @@ -228,5 +228,5 @@ Patches, comments and suggestions are very very welcome. Ulf Hermenau for helping me out with traditional chinese. - André Smoktun and Christian Frömmel for supporting me with + André Smoktun and Christian Frömmel for supporting me with hardware and listening to my problems very patiently. diff --git a/trunk/Documentation/dvb/contributors.txt b/trunk/Documentation/dvb/contributors.txt index 4865addebe1c..4c33cced5f65 100644 --- a/trunk/Documentation/dvb/contributors.txt +++ b/trunk/Documentation/dvb/contributors.txt @@ -66,7 +66,7 @@ Michael Dreher Andreas 'randy' Weinberger for the support of the Fujitsu-Siemens Activy budget DVB-S -Kenneth Aafløy +Kenneth Aafløy for adding support for Typhoon DVB-S budget card Ernst Peinlich diff --git a/trunk/Documentation/fb/arkfb.txt b/trunk/Documentation/fb/arkfb.txt deleted file mode 100644 index e8487a9d6a05..000000000000 --- a/trunk/Documentation/fb/arkfb.txt +++ /dev/null @@ -1,68 +0,0 @@ - - arkfb - fbdev driver for ARK Logic chips - ======================================== - - -Supported Hardware -================== - - ARK 2000PV chip - ICS 5342 ramdac - - - only BIOS initialized VGA devices supported - - probably not working on big endian - - -Supported Features -================== - - * 4 bpp pseudocolor modes (with 18bit palette, two variants) - * 8 bpp pseudocolor mode (with 18bit palette) - * 16 bpp truecolor modes (RGB 555 and RGB 565) - * 24 bpp truecolor mode (RGB 888) - * 32 bpp truecolor mode (RGB 888) - * text mode (activated by bpp = 0) - * doublescan mode variant (not available in text mode) - * panning in both directions - * suspend/resume support - -Text mode is supported even in higher resolutions, but there is limitation to -lower pixclocks (i got maximum about 70 MHz, it is dependent on specific -hardware). This limitation is not enforced by driver. Text mode supports 8bit -wide fonts only (hardware limitation) and 16bit tall fonts (driver -limitation). Unfortunately character attributes (like color) in text mode are -broken for unknown reason, so its usefulness is limited. - -There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with -packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode -with interleaved planes (1 byte interleave), MSB first. Both modes support -8bit wide fonts only (driver limitation). - -Suspend/resume works on systems that initialize video card during resume and -if device is active (for example used by fbcon). - - -Missing Features -================ -(alias TODO list) - - * secondary (not initialized by BIOS) device support - * big endian support - * DPMS support - * MMIO support - * interlaced mode variant - * support for fontwidths != 8 in 4 bpp modes - * support for fontheight != 16 in text mode - * hardware cursor - * vsync synchronization - * feature connector support - * acceleration support (8514-like 2D) - - -Known bugs -========== - - * character attributes (and cursor) in text mode are broken - --- -Ondrej Zajicek diff --git a/trunk/Documentation/fb/aty128fb.txt b/trunk/Documentation/fb/aty128fb.txt index b605204fcfe1..069262fb619d 100644 --- a/trunk/Documentation/fb/aty128fb.txt +++ b/trunk/Documentation/fb/aty128fb.txt @@ -54,8 +54,8 @@ Accepted options: noaccel - do not use acceleration engine. It is default. accel - use acceleration engine. Not finished. -vmode:x - chooses PowerMacintosh video mode . Deprecated. -cmode:x - chooses PowerMacintosh colour mode . Deprecated. +vmode:x - chooses PowerMacintosh video mode . Depreciated. +cmode:x - chooses PowerMacintosh colour mode . Depreciated. - selects startup videomode. See modedb.txt for detailed explanation. Default is 640x480x8bpp. diff --git a/trunk/Documentation/fb/framebuffer.txt b/trunk/Documentation/fb/framebuffer.txt index b3e3a0356839..610e7801207b 100644 --- a/trunk/Documentation/fb/framebuffer.txt +++ b/trunk/Documentation/fb/framebuffer.txt @@ -215,11 +215,11 @@ vertical retrace time is the sum of the upper margin, the lower margin and the vsync length. +----------+---------------------------------------------+----------+-------+ - | | ↑ | | | + | | ^ | | | | | |upper_margin | | | - | | ↓ | | | + | | ¥ | | | +----------###############################################----------+-------+ - | # ↑ # | | + | # ^ # | | | # | # | | | # | # | | | # | # | | @@ -238,15 +238,15 @@ vsync length. | # | # | | | # | # | | | # | # | | - | # ↓ # | | + | # ¥ # | | +----------###############################################----------+-------+ - | | ↑ | | | + | | ^ | | | | | |lower_margin | | | - | | ↓ | | | + | | ¥ | | | +----------+---------------------------------------------+----------+-------+ - | | ↑ | | | + | | ^ | | | | | |vsync_len | | | - | | ↓ | | | + | | ¥ | | | +----------+---------------------------------------------+----------+-------+ The frame buffer device expects all horizontal timings in number of dotclocks diff --git a/trunk/Documentation/fb/imacfb.txt b/trunk/Documentation/fb/imacfb.txt index 316ec9bb7deb..759028545a7e 100644 --- a/trunk/Documentation/fb/imacfb.txt +++ b/trunk/Documentation/fb/imacfb.txt @@ -17,7 +17,7 @@ How to use it? ============== Imacfb does not have any kind of autodetection of your machine. -You have to add the following kernel parameters in your elilo.conf: +You have to add the fillowing kernel parameters in your elilo.conf: Macbook : video=imacfb:macbook MacMini : diff --git a/trunk/Documentation/fb/sstfb.txt b/trunk/Documentation/fb/sstfb.txt index 550ca775a4cb..df27f5bf15db 100644 --- a/trunk/Documentation/fb/sstfb.txt +++ b/trunk/Documentation/fb/sstfb.txt @@ -2,9 +2,9 @@ Introduction This is a frame buffer device driver for 3dfx' Voodoo Graphics - (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based + (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based video boards. It's highly experimental code, but is guaranteed to work - on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards, + on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards, and with me "between chair and keyboard". Some people tested other combinations and it seems that it works. The main page is located at , and if diff --git a/trunk/Documentation/fb/vt8623fb.txt b/trunk/Documentation/fb/vt8623fb.txt deleted file mode 100644 index f654576c56b7..000000000000 --- a/trunk/Documentation/fb/vt8623fb.txt +++ /dev/null @@ -1,64 +0,0 @@ - - vt8623fb - fbdev driver for graphics core in VIA VT8623 chipset - =============================================================== - - -Supported Hardware -================== - - VIA VT8623 [CLE266] chipset and its graphics core - (known as CastleRock or Unichrome) - -I tested vt8623fb on VIA EPIA ML-6000 - - -Supported Features -================== - - * 4 bpp pseudocolor modes (with 18bit palette, two variants) - * 8 bpp pseudocolor mode (with 18bit palette) - * 16 bpp truecolor mode (RGB 565) - * 32 bpp truecolor mode (RGB 888) - * text mode (activated by bpp = 0) - * doublescan mode variant (not available in text mode) - * panning in both directions - * suspend/resume support - * DPMS support - -Text mode is supported even in higher resolutions, but there is limitation to -lower pixclocks (maximum about 100 MHz). This limitation is not enforced by -driver. Text mode supports 8bit wide fonts only (hardware limitation) and -16bit tall fonts (driver limitation). - -There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with -packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode -with interleaved planes (1 byte interleave), MSB first. Both modes support -8bit wide fonts only (driver limitation). - -Suspend/resume works on systems that initialize video card during resume and -if device is active (for example used by fbcon). - - -Missing Features -================ -(alias TODO list) - - * secondary (not initialized by BIOS) device support - * MMIO support - * interlaced mode variant - * support for fontwidths != 8 in 4 bpp modes - * support for fontheight != 16 in text mode - * hardware cursor - * video overlay support - * vsync synchronization - * acceleration support (8514-like 2D, busmaster transfers) - - -Known bugs -========== - - * cursor disable in text mode doesn't work - - --- -Ondrej Zajicek diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index c6322c760348..2291ff620d93 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -59,15 +59,6 @@ Who: Dan Dennedy , Stefan Richter --------------------------- -What: old NCR53C9x driver -When: October 2007 -Why: Replaced by the much better esp_scsi driver. Actual low-level - driver can ported over almost trivially. -Who: David Miller - Christoph Hellwig - ---------------------------- - What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. When: December 2006 Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6 @@ -278,6 +269,14 @@ Who: Richard Purdie --------------------------- +What: i8xx_tco watchdog driver +When: in 2.6.22 +Why: the i8xx_tco watchdog driver has been replaced by the iTCO_wdt + watchdog driver. +Who: Wim Van Sebroeck + +--------------------------- + What: Multipath cached routing support in ipv4 When: in 2.6.23 Why: Code was merged, then submitter immediately disappeared leaving diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index d866551be037..59c14159cc47 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -54,7 +54,7 @@ ata *); locking rules: all may block, none have BKL - i_mutex(inode) + i_sem(inode) lookup: yes create: yes link: yes (both) @@ -74,7 +74,7 @@ setxattr: yes getxattr: no listxattr: no removexattr: yes - Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on + Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on victim. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. ->truncate() is never called directly - it's a callback, not a @@ -461,7 +461,7 @@ doesn't take the BKL. ->read on directories probably must go away - we should just enforce -EISDIR in sys_read() and friends. -->fsync() has i_mutex on inode. +->fsync() has i_sem on inode. --------------------------- dquot_operations ------------------------------- prototypes: diff --git a/trunk/Documentation/filesystems/hpfs.txt b/trunk/Documentation/filesystems/hpfs.txt index fa45c3baed98..38aba03efc5e 100644 --- a/trunk/Documentation/filesystems/hpfs.txt +++ b/trunk/Documentation/filesystems/hpfs.txt @@ -290,7 +290,7 @@ History 2.07 More fixes for Warp Server. Now it really works 2.08 Creating new files is not so slow on large disks An attempt to sync deleted file does not generate filesystem error -2.09 Fixed error on extremely fragmented files +2.09 Fixed error on extremly fragmented files vim: set textwidth=80: diff --git a/trunk/Documentation/filesystems/ntfs.txt b/trunk/Documentation/filesystems/ntfs.txt index 8ee10ec88293..81779068b09b 100644 --- a/trunk/Documentation/filesystems/ntfs.txt +++ b/trunk/Documentation/filesystems/ntfs.txt @@ -349,7 +349,7 @@ end of the line. Note the "Should sync?" parameter "nosync" means that the two mirrors are already in sync which will be the case on a clean shutdown of Windows. If the mirrors are not clean, you can specify the "sync" option instead of "nosync" -and the Device-Mapper driver will then copy the entirety of the "Source Device" +and the Device-Mapper driver will then copy the entirey of the "Source Device" to the "Target Device" or if you specified multipled target devices to all of them. diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt index 8756a07f4dc3..4f3e84c520a5 100644 --- a/trunk/Documentation/filesystems/proc.txt +++ b/trunk/Documentation/filesystems/proc.txt @@ -229,7 +229,7 @@ Table 1-3: Kernel info in /proc mounts Mounted filesystems net Networking info (see text) partitions Table of partitions known to the system - pci Deprecated info of PCI bus (new way -> /proc/bus/pci/, + pci Depreciated info of PCI bus (new way -> /proc/bus/pci/, decoupled by lspci (2.4) rtc Real time clock scsi SCSI info (see text) diff --git a/trunk/Documentation/filesystems/relay.txt b/trunk/Documentation/filesystems/relay.txt index 18d23f9a18c7..7fbb6ffe5769 100644 --- a/trunk/Documentation/filesystems/relay.txt +++ b/trunk/Documentation/filesystems/relay.txt @@ -351,7 +351,7 @@ If the current buffer is full, i.e. all sub-buffers remain unconsumed, the callback returns 0 to indicate that the buffer switch should not occur yet, i.e. until the consumer has had a chance to read the current set of ready sub-buffers. For the relay_buf_full() function -to make sense, the consumer is responsible for notifying the relay +to make sense, the consumer is reponsible for notifying the relay interface when sub-buffers have been consumed via relay_subbufs_consumed(). Any subsequent attempts to write into the buffer will again invoke the subbuf_start() callback with the same diff --git a/trunk/Documentation/filesystems/xip.txt b/trunk/Documentation/filesystems/xip.txt index 3cc4010521a0..6c0cef10eb4d 100644 --- a/trunk/Documentation/filesystems/xip.txt +++ b/trunk/Documentation/filesystems/xip.txt @@ -19,7 +19,7 @@ completely. With execute-in-place, read&write type operations are performed directly from/to the memory backed storage device. For file mappings, the storage device itself is mapped directly into userspace. -This implementation was initially written for shared memory segments between +This implementation was initialy written for shared memory segments between different virtual machines on s390 hardware to allow multiple machines to share the same binaries and libraries. diff --git a/trunk/Documentation/fujitsu/frv/gdbstub.txt b/trunk/Documentation/fujitsu/frv/gdbstub.txt index b92bfd902a4e..9304fb36ae8a 100644 --- a/trunk/Documentation/fujitsu/frv/gdbstub.txt +++ b/trunk/Documentation/fujitsu/frv/gdbstub.txt @@ -126,5 +126,5 @@ GDB stub and the debugger: Furthermore, the GDB stub will intercept a number of exceptions automatically if they are caused by kernel execution. It will also intercept BUG() macro -invocation. +invokation. diff --git a/trunk/Documentation/gpio.txt b/trunk/Documentation/gpio.txt index e8be0abb346c..f8528db967fa 100644 --- a/trunk/Documentation/gpio.txt +++ b/trunk/Documentation/gpio.txt @@ -66,9 +66,7 @@ registers; another might implement it by delegating through abstractions used for several very different kinds of GPIO controller. That said, if the convention is supported on their platform, drivers should -use it when possible. Platforms should declare GENERIC_GPIO support in -Kconfig (boolean true), which multi-platform drivers can depend on when -using the include file: +use it when possible: #include diff --git a/trunk/Documentation/hwmon/adm1026 b/trunk/Documentation/hwmon/adm1026 index f4327db2307e..473c689d7924 100644 --- a/trunk/Documentation/hwmon/adm1026 +++ b/trunk/Documentation/hwmon/adm1026 @@ -80,7 +80,7 @@ temperature sensor inputs. Both the PWM output and the DAC output can be used to control fan speed. Usually only one of these two outputs will be used. Write the minimum PWM or DAC value to the appropriate control register. Then set the low temperature limit in the tmin values for each -temperature sensor. The range of control is fixed at 20 °C, and the +temperature sensor. The range of control is fixed at 20 °C, and the largest difference between current and tmin of the temperature sensors sets the control output. See the datasheet for several example circuits for controlling fan speed with the PWM and DAC outputs. The fan speed sensors diff --git a/trunk/Documentation/hwmon/gl518sm b/trunk/Documentation/hwmon/gl518sm index 229f8b789185..ce0881883bca 100644 --- a/trunk/Documentation/hwmon/gl518sm +++ b/trunk/Documentation/hwmon/gl518sm @@ -13,7 +13,7 @@ Supported chips: Authors: Frodo Looijaard , - Kyösti Mälkki + Kyösti Mälkki Hong-Gunn Chew Jean Delvare diff --git a/trunk/Documentation/hwmon/lm83 b/trunk/Documentation/hwmon/lm83 index a04d1fe9269c..f7aad1489cb0 100644 --- a/trunk/Documentation/hwmon/lm83 +++ b/trunk/Documentation/hwmon/lm83 @@ -45,7 +45,7 @@ Unconfirmed motherboards: The LM82 is confirmed to have been found on most AMD Geode reference designs and test platforms. -The driver has been successfully tested by Magnus Forsström, who I'd +The driver has been successfully tested by Magnus Forsström, who I'd like to thank here. More testers will be of course welcome. The fact that the LM83 is only scarcely used can be easily explained. diff --git a/trunk/Documentation/hwmon/sis5595 b/trunk/Documentation/hwmon/sis5595 index 4f8877a34f37..b7ae36b8cdf5 100644 --- a/trunk/Documentation/hwmon/sis5595 +++ b/trunk/Documentation/hwmon/sis5595 @@ -8,7 +8,7 @@ Supported chips: Datasheet: Publicly available at the Silicon Integrated Systems Corp. site. Authors: - Kyösti Mälkki , + Kyösti Mälkki , Mark D. Studebaker , Aurelien Jarno 2.6 port diff --git a/trunk/Documentation/hwmon/via686a b/trunk/Documentation/hwmon/via686a index d651b25f7519..a936fb3824b2 100644 --- a/trunk/Documentation/hwmon/via686a +++ b/trunk/Documentation/hwmon/via686a @@ -8,7 +8,7 @@ Supported chips: Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/) Authors: - Kyösti Mälkki , + Kyösti Mälkki , Mark D. Studebaker Bob Dougherty (Some conversion-factor data were contributed by diff --git a/trunk/Documentation/hwmon/w83792d b/trunk/Documentation/hwmon/w83792d index 14a668ed8aaa..8171c285bb55 100644 --- a/trunk/Documentation/hwmon/w83792d +++ b/trunk/Documentation/hwmon/w83792d @@ -107,7 +107,7 @@ Known problems: by CR[0x49h]. - The function of vid and vrm has not been finished, because I'm NOT very familiar with them. Adding support is welcome. -  - The function of chassis open detection needs more tests. +  - The function of chassis open detection needs more tests. - If you have ASUS server board and chip was not found: Then you will need to upgrade to latest (or beta) BIOS. If it does not help please contact us. diff --git a/trunk/Documentation/i2c/busses/i2c-i810 b/trunk/Documentation/i2c/busses/i2c-i810 index 778210ee1583..83c3b9743c3c 100644 --- a/trunk/Documentation/i2c/busses/i2c-i810 +++ b/trunk/Documentation/i2c/busses/i2c-i810 @@ -7,7 +7,7 @@ Supported adapters: Authors: Frodo Looijaard , Philip Edelbrock , - Kyösti Mälkki , + Kyösti Mälkki , Ralph Metzler , Mark D. Studebaker diff --git a/trunk/Documentation/i2c/busses/i2c-sis96x b/trunk/Documentation/i2c/busses/i2c-sis96x index 266481fd26e2..08d7b2dac69a 100644 --- a/trunk/Documentation/i2c/busses/i2c-sis96x +++ b/trunk/Documentation/i2c/busses/i2c-sis96x @@ -60,7 +60,7 @@ Mark D. Studebaker - design hints and bug fixes Alexander Maylsh - ditto, plus an important datasheet... almost the one I really wanted -Hans-Günter Lütke Uphues +Hans-Günter Lütke Uphues - patch for SiS735 Robert Zwerus - testing for SiS645DX diff --git a/trunk/Documentation/i2c/busses/i2c-via b/trunk/Documentation/i2c/busses/i2c-via index 343870661ac3..55edfe1a640b 100644 --- a/trunk/Documentation/i2c/busses/i2c-via +++ b/trunk/Documentation/i2c/busses/i2c-via @@ -4,7 +4,7 @@ Supported adapters: * VIA Technologies, InC. VT82C586B Datasheet: Publicly available at the VIA website -Author: Kyösti Mälkki +Author: Kyösti Mälkki Description ----------- diff --git a/trunk/Documentation/i2c/busses/i2c-viapro b/trunk/Documentation/i2c/busses/i2c-viapro index 06b4be3ef6d8..775f489e86f6 100644 --- a/trunk/Documentation/i2c/busses/i2c-viapro +++ b/trunk/Documentation/i2c/busses/i2c-viapro @@ -17,7 +17,7 @@ Supported adapters: Datasheet: available on request and under NDA from VIA Authors: - Kyösti Mälkki , + Kyösti Mälkki , Mark D. Studebaker , Jean Delvare diff --git a/trunk/Documentation/i2c/i2c-protocol b/trunk/Documentation/i2c/i2c-protocol index 579b92d5f3a3..b4022c914210 100644 --- a/trunk/Documentation/i2c/i2c-protocol +++ b/trunk/Documentation/i2c/i2c-protocol @@ -68,7 +68,7 @@ We have found some I2C devices that needs the following modifications: Flags I2C_M_IGNORE_NAK Normally message is interrupted immediately if there is [NA] from the - client. Setting this flag treats any [NA] as [A], and all of + client. Setting this flag treats any [NA] as [A], and all of message is sent. These messages may still fail to SCL lo->hi timeout. diff --git a/trunk/Documentation/i2o/README b/trunk/Documentation/i2o/README index 0ebf58c73f54..9aa6ddb446eb 100644 --- a/trunk/Documentation/i2o/README +++ b/trunk/Documentation/i2o/README @@ -30,13 +30,13 @@ Juha Sievanen, University of Helsinki Finland Bug fixes Core code extensions -Auvo Häkkinen, University of Helsinki Finland +Auvo Häkkinen, University of Helsinki Finland LAN OSM code /Proc interface to LAN class Bug fixes Core code extensions -Taneli Vähäkangas, University of Helsinki Finland +Taneli Vähäkangas, University of Helsinki Finland Fixes to i2o_config CREDITS diff --git a/trunk/Documentation/i386/boot.txt b/trunk/Documentation/i386/boot.txt index d01b7a2a0f2e..6498666ea330 100644 --- a/trunk/Documentation/i386/boot.txt +++ b/trunk/Documentation/i386/boot.txt @@ -2,7 +2,7 @@ ---------------------------- H. Peter Anvin - Last update 2007-05-07 + Last update 2007-03-06 On the i386 platform, the Linux kernel uses a rather complicated boot convention. This has evolved partially due to historical aspects, as @@ -11,7 +11,7 @@ bootable image, the complicated PC memory model and due to changed expectations in the PC industry caused by the effective demise of real-mode DOS as a mainstream operating system. -Currently, the following versions of the Linux/i386 boot protocol exist. +Currently, four versions of the Linux/i386 boot protocol exist. Old kernels: zImage/Image support only. Some very early kernels may not even support a command line. @@ -183,9 +183,9 @@ filled out, however: a version number. Otherwise, enter 0xFF here. Assigned boot loader ids: - 0 LILO (0x00 reserved for pre-2.00 bootloader) + 0 LILO 1 Loadlin - 2 bootsect-loader (0x20, all other values reserved) + 2 bootsect-loader 3 SYSLINUX 4 EtherBoot 5 ELILO @@ -210,9 +210,6 @@ filled out, however: additional data (such as the kernel command line) moved in addition to the real-mode kernel itself. - The unit is bytes starting with the beginning of the boot - sector. - ramdisk_image, ramdisk_size: If your boot loader has loaded an initial ramdisk (initrd), set ramdisk_image to the 32-bit pointer to the ramdisk data @@ -281,54 +278,14 @@ command line is entered using the following protocol: field. -**** MEMORY LAYOUT OF THE REAL-MODE CODE - -The real-mode code requires a stack/heap to be set up, as well as -memory allocated for the kernel command line. This needs to be done -in the real-mode accessible memory in bottom megabyte. - -It should be noted that modern machines often have a sizable Extended -BIOS Data Area (EBDA). As a result, it is advisable to use as little -of the low megabyte as possible. - -Unfortunately, under the following circumstances the 0x90000 memory -segment has to be used: - - - When loading a zImage kernel ((loadflags & 0x01) == 0). - - When loading a 2.01 or earlier boot protocol kernel. - - -> For the 2.00 and 2.01 boot protocols, the real-mode code - can be loaded at another address, but it is internally - relocated to 0x90000. For the "old" protocol, the - real-mode code must be loaded at 0x90000. - -When loading at 0x90000, avoid using memory above 0x9a000. - -For boot protocol 2.02 or higher, the command line does not have to be -located in the same 64K segment as the real-mode setup code; it is -thus permitted to give the stack/heap the full 64K segment and locate -the command line above it. - -The kernel command line should not be located below the real-mode -code, nor should it be located in high memory. - - **** SAMPLE BOOT CONFIGURATION As a sample configuration, assume the following layout of the real -mode segment: - - When loading below 0x90000, use the entire segment: - - 0x0000-0x7fff Real mode kernel - 0x8000-0xdfff Stack and heap - 0xe000-0xffff Kernel command line +mode segment (this is a typical, and recommended layout): - When loading at 0x90000 OR the protocol version is 2.01 or earlier: - - 0x0000-0x7fff Real mode kernel - 0x8000-0x97ff Stack and heap - 0x9800-0x9fff Kernel command line + 0x0000-0x7FFF Real mode kernel + 0x8000-0x8FFF Stack and heap + 0x9000-0x90FF Kernel command line Such a boot loader should enter the following fields in the header: @@ -344,33 +301,22 @@ Such a boot loader should enter the following fields in the header: ramdisk_image = ; ramdisk_size = ; } - - if ( protocol >= 0x0202 && loadflags & 0x01 ) - heap_end = 0xe000; - else - heap_end = 0x9800; - if ( protocol >= 0x0201 ) { - heap_end_ptr = heap_end - 0x200; + heap_end_ptr = 0x9000 - 0x200; loadflags |= 0x80; /* CAN_USE_HEAP */ } - if ( protocol >= 0x0202 ) { - cmd_line_ptr = base_ptr + heap_end; - strcpy(cmd_line_ptr, cmdline); + cmd_line_ptr = base_ptr + 0x9000; } else { cmd_line_magic = 0xA33F; - cmd_line_offset = heap_end; - setup_move_size = heap_end + strlen(cmdline)+1; - strcpy(base_ptr+cmd_line_offset, cmdline); + cmd_line_offset = 0x9000; + setup_move_size = 0x9100; } } else { /* Very old kernel */ - heap_end = 0x9800; - cmd_line_magic = 0xA33F; - cmd_line_offset = heap_end; + cmd_line_offset = 0x9000; /* A very old kernel MUST have its real-mode code loaded at 0x90000 */ @@ -378,11 +324,12 @@ Such a boot loader should enter the following fields in the header: if ( base_ptr != 0x90000 ) { /* Copy the real-mode kernel */ memcpy(0x90000, base_ptr, (setup_sects+1)*512); + /* Copy the command line */ + memcpy(0x99000, base_ptr+0x9000, 256); + base_ptr = 0x90000; /* Relocated */ } - strcpy(0x90000+cmd_line_offset, cmdline); - /* It is recommended to clear memory up to the 32K mark */ memset(0x90000 + (setup_sects+1)*512, 0, (64-(setup_sects+1))*512); @@ -428,11 +375,10 @@ conflict with actual kernel options now or in the future. line is parsed. mem= - is an integer in C notation optionally followed by - (case insensitive) K, M, G, T, P or E (meaning << 10, << 20, - << 30, << 40, << 50 or << 60). This specifies the end of - memory to the kernel. This affects the possible placement of - an initrd, since an initrd should be placed near end of + is an integer in C notation optionally followed by K, M + or G (meaning << 10, << 20 or << 30). This specifies the end + of memory to the kernel. This affects the possible placement + of an initrd, since an initrd should be placed near end of memory. Note that this is an option to *both* the kernel and the bootloader! @@ -482,7 +428,7 @@ In our example from above, we would do: /* Set up the real-mode kernel stack */ _SS = seg; - _SP = heap_end; + _SP = 0x9000; /* Load SP immediately after loading SS! */ _DS = _ES = _FS = _GS = seg; jmp_far(seg+0x20, 0); /* Run the kernel */ @@ -514,9 +460,8 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and code32_start: A 32-bit flat-mode routine *jumped* to immediately after the transition to protected mode, but before the kernel is - uncompressed. No segments, except CS, are guaranteed to be - set up (current kernels do, but older ones do not); you should - set them up to BOOT_DS (0x18) yourself. + uncompressed. No segments, except CS, are set up; you should + set them up to KERNEL_DS (0x18) yourself. After completing your hook, you should jump to the address that was in this field before your boot loader overwrote it. diff --git a/trunk/Documentation/input/atarikbd.txt b/trunk/Documentation/input/atarikbd.txt index ab050621e20f..668f4d0d97d6 100644 --- a/trunk/Documentation/input/atarikbd.txt +++ b/trunk/Documentation/input/atarikbd.txt @@ -179,9 +179,9 @@ reporting mode for joystick 1, with both buttons being logically assigned to the mouse. After any joystick command, the ikbd assumes that joysticks are connected to both Joystick0 and Joystick1. Any mouse command (except MOUSE DISABLE) then causes port 0 to again be scanned as if it were a mouse, and -both buttons are logically connected to it. If a mouse disable command is +both buttons are logically connected to it. If a mouse diable command is received while port 0 is presumed to be a mouse, the button is logically -assigned to Joystick1 (until the mouse is reenabled by another mouse command). +assigned to Joystick1 ( until the mouse is reenabled by another mouse command). 9. ikbd Command Set diff --git a/trunk/Documentation/input/xpad.txt b/trunk/Documentation/input/xpad.txt index aae0d404c566..5427bdf225ed 100644 --- a/trunk/Documentation/input/xpad.txt +++ b/trunk/Documentation/input/xpad.txt @@ -65,15 +65,15 @@ of buttons, see section 0.3 - Unknown Controllers I've tested this with Stepmania, and it works quite well. -0.3 Unknown Controllers +0.3 Unkown Controllers ---------------------- -If you have an unknown xbox controller, it should work just fine with +If you have an unkown xbox controller, it should work just fine with the default settings. HOWEVER if you have an unknown dance pad not listed below, it will not work UNLESS you set "dpad_to_buttons" to 1 in the module configuration. -PLEASE, if you have an unknown controller, email Dom with +PLEASE if you have an unkown controller, email Dom with a dump from /proc/bus/usb and a description of the pad (manufacturer, country, whether it is a dance pad or normal controller) so that we can add your pad to the list of supported devices, ensuring that it will work out of the diff --git a/trunk/Documentation/isdn/CREDITS b/trunk/Documentation/isdn/CREDITS index 7c17c837064f..e1b3023efaa8 100644 --- a/trunk/Documentation/isdn/CREDITS +++ b/trunk/Documentation/isdn/CREDITS @@ -2,7 +2,7 @@ I want to thank all who contributed to this project and especially to: (in alphabetical order) -Thomas Bogendörfer (tsbogend@bigbug.franken.de) +Thomas Bogendörfer (tsbogend@bigbug.franken.de) Tester, lots of bugfixes and hints. Alan Cox (alan@redhat.com) @@ -11,7 +11,7 @@ Alan Cox (alan@redhat.com) Henner Eisen (eis@baty.hanse.de) For X.25 implementation. -Volker Götz (volker@oops.franken.de) +Volker Götz (volker@oops.franken.de) For contribution of man-pages, the imontty-tool and a perfect maintaining of the mailing-list at hub-wue. diff --git a/trunk/Documentation/isdn/README b/trunk/Documentation/isdn/README index 6783437f21c2..761595243931 100644 --- a/trunk/Documentation/isdn/README +++ b/trunk/Documentation/isdn/README @@ -402,7 +402,7 @@ README for the ISDN-subsystem the script tools/tcltk/isdnmon. You can add actions for line-status changes. See the comments at the beginning of the script for how to do that. There are other tty-based tools in the tools-subdirectory - contributed by Michael Knigge (imon), Volker Götz (imontty) and + contributed by Michael Knigge (imon), Volker Götz (imontty) and Andreas Kool (isdnmon). l) For initial testing, you can set the verbose-level to 2 (default: 0). diff --git a/trunk/Documentation/isdn/README.icn b/trunk/Documentation/isdn/README.icn index 13f833d4e910..a5f55eadb3ca 100644 --- a/trunk/Documentation/isdn/README.icn +++ b/trunk/Documentation/isdn/README.icn @@ -3,8 +3,8 @@ $Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $ You can get the ICN-ISDN-card from: Thinking Objects Software GmbH -Versbacher Röthe 159 -97078 Würzburg +Versbacher Röthe 159 +97078 Würzburg Tel: +49 931 2877950 Fax: +49 931 2877951 diff --git a/trunk/Documentation/java.txt b/trunk/Documentation/java.txt index 3cce3fbb6644..c768dc63b34e 100644 --- a/trunk/Documentation/java.txt +++ b/trunk/Documentation/java.txt @@ -390,7 +390,7 @@ the execution bit, then just do originally by Brian A. Lantz, brian@lantz.com -heavily edited for binfmt_misc by Richard Günther +heavily edited for binfmt_misc by Richard Günther new scripts by Colin J. Watson added executable Jar file support by Kurt Huwig diff --git a/trunk/Documentation/kernel-docs.txt b/trunk/Documentation/kernel-docs.txt index d9e3b199929b..c68dafeda7a7 100644 --- a/trunk/Documentation/kernel-docs.txt +++ b/trunk/Documentation/kernel-docs.txt @@ -236,7 +236,7 @@ * Title: "Design and Implementation of the Second Extended Filesystem" - Author: Rémy Card, Theodore Ts'o, Stephen Tweedie. + Author: Rémy Card, Theodore Ts'o, Stephen Tweedie. URL: http://web.mit.edu/tytso/www/linux/ext2intro.html Keywords: ext2, linux fs history, inode, directory, link, devices, VFS, physical structure, performance, benchmarks, ext2fs library, diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 09220a1e22d9..6b8ad06846c4 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -754,6 +754,14 @@ and is between 256 and 4096 characters. It is defined in the file inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver Format: + combined_mode= [HW] control which driver uses IDE ports in combined + mode: legacy IDE driver, libata, or both + (in the libata case, libata.atapi_enabled=1 may be + useful as well). Note that using the ide or libata + options may affect your device naming (e.g. by + changing hdc to sdb). + Format: combined (default), ide, or libata + inttest= [IA64] io7= [HW] IO7 for Marvel based alpha systems diff --git a/trunk/Documentation/m68k/README.buddha b/trunk/Documentation/m68k/README.buddha index 3ea9827ba3c7..ef484a719bb9 100644 --- a/trunk/Documentation/m68k/README.buddha +++ b/trunk/Documentation/m68k/README.buddha @@ -204,7 +204,7 @@ always shows a "no IRQ here" on the Buddha, and accesses to the third IDE port are going into data's Nirwana on the Buddha. - Jens Schönfeld february 19th, 1997 + Jens Schönfeld february 19th, 1997 updated may 27th, 1997 eMail: sysop@nostlgic.tng.oche.de diff --git a/trunk/Documentation/magic-number.txt b/trunk/Documentation/magic-number.txt index bd450e797558..0e740c812d12 100644 --- a/trunk/Documentation/magic-number.txt +++ b/trunk/Documentation/magic-number.txt @@ -129,7 +129,7 @@ SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h -EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c +EEPROM_MAGIC_VALUE 0X5ab478d2 lanai_dev drivers/atm/lanai.c HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h diff --git a/trunk/Documentation/md.txt b/trunk/Documentation/md.txt index 5818628207b5..2202f5dc8ac2 100644 --- a/trunk/Documentation/md.txt +++ b/trunk/Documentation/md.txt @@ -178,21 +178,6 @@ All md devices contain: The size should be at least PAGE_SIZE (4k) and should be a power of 2. This can only be set while assembling an array - layout - The "layout" for the array for the particular level. This is - simply a number that is interpretted differently by different - levels. It can be written while assembling an array. - - reshape_position - This is either "none" or a sector number within the devices of - the array where "reshape" is up to. If this is set, the three - attributes mentioned above (raid_disks, chunk_size, layout) can - potentially have 2 values, an old and a new value. If these - values differ, reading the attribute returns - new (old) - and writing will effect the 'new' value, leaving the 'old' - unchanged. - component_size For arrays with data redundancy (i.e. not raid0, linear, faulty, multipath), all components must be the same size - or at least @@ -208,6 +193,11 @@ All md devices contain: 1.2 (newer format in varying locations) or "none" indicating that the kernel isn't managing metadata at all. + layout + The "layout" for the array for the particular level. This is + simply a number that is interpretted differently by different + levels. It can be written while assembling an array. + resync_start The point at which resync should start. If no resync is needed, this will be a very large number. At array creation it will @@ -269,6 +259,29 @@ All md devices contain: like active, but no writes have been seen for a while (safe_mode_delay). + sync_speed_min + sync_speed_max + This are similar to /proc/sys/dev/raid/speed_limit_{min,max} + however they only apply to the particular array. + If no value has been written to these, of if the word 'system' + is written, then the system-wide value is used. If a value, + in kibibytes-per-second is written, then it is used. + When the files are read, they show the currently active value + followed by "(local)" or "(system)" depending on whether it is + a locally set or system-wide value. + + sync_completed + This shows the number of sectors that have been completed of + whatever the current sync_action is, followed by the number of + sectors in total that could need to be processed. The two + numbers are separated by a '/' thus effectively showing one + value, a fraction of the process that is complete. + + sync_speed + This shows the current actual speed, in K/sec, of the current + sync_action. It is averaged over the last 30 seconds. + + As component devices are added to an md array, they appear in the 'md' directory as new directories named dev-XXX @@ -399,35 +412,6 @@ also have Note that the numbers are 'bit' numbers, not 'block' numbers. They should be scaled by the bitmap_chunksize. - sync_speed_min - sync_speed_max - This are similar to /proc/sys/dev/raid/speed_limit_{min,max} - however they only apply to the particular array. - If no value has been written to these, of if the word 'system' - is written, then the system-wide value is used. If a value, - in kibibytes-per-second is written, then it is used. - When the files are read, they show the currently active value - followed by "(local)" or "(system)" depending on whether it is - a locally set or system-wide value. - - sync_completed - This shows the number of sectors that have been completed of - whatever the current sync_action is, followed by the number of - sectors in total that could need to be processed. The two - numbers are separated by a '/' thus effectively showing one - value, a fraction of the process that is complete. - - sync_speed - This shows the current actual speed, in K/sec, of the current - sync_action. It is averaged over the last 30 seconds. - - suspend_lo - suspend_hi - The two values, given as numbers of sectors, indicate a range - within the array where IO will be blocked. This is currently - only supported for raid4/5/6. - - Each active md device may also have attributes specific to the personality module that manages it. These are specific to the implementation of the module and could diff --git a/trunk/Documentation/netlabel/introduction.txt b/trunk/Documentation/netlabel/introduction.txt index 5ecd8d1dcf4e..a4ffba1694c8 100644 --- a/trunk/Documentation/netlabel/introduction.txt +++ b/trunk/Documentation/netlabel/introduction.txt @@ -30,7 +30,7 @@ The communication layer exists to allow NetLabel configuration and monitoring from user space. The NetLabel communication layer uses a message based protocol built on top of the Generic NETLINK transport mechanism. The exact formatting of these NetLabel messages as well as the Generic NETLINK family -names can be found in the 'net/netlabel/' directory as comments in the +names can be found in the the 'net/netlabel/' directory as comments in the header files as well as in 'include/net/netlabel.h'. * Security Module API diff --git a/trunk/Documentation/networking/6pack.txt b/trunk/Documentation/networking/6pack.txt index d0777a1200e1..48ed2b711bd2 100644 --- a/trunk/Documentation/networking/6pack.txt +++ b/trunk/Documentation/networking/6pack.txt @@ -1,6 +1,6 @@ This is the 6pack-mini-HOWTO, written by -Andreas Könsgen DG3KQ +Andreas Könsgen DG3KQ Internet: ajk@iehk.rwth-aachen.de AMPR-net: dg3kq@db0pra.ampr.org AX.25: dg3kq@db0ach.#nrw.deu.eu diff --git a/trunk/Documentation/networking/NAPI_HOWTO.txt b/trunk/Documentation/networking/NAPI_HOWTO.txt index 7907435a661c..fb8dc6422a52 100644 --- a/trunk/Documentation/networking/NAPI_HOWTO.txt +++ b/trunk/Documentation/networking/NAPI_HOWTO.txt @@ -160,7 +160,7 @@ on current cpu. This primitive is called by dev->poll(), when it completes its work. The device cannot be out of poll list at this call, if it is then clearly it is a BUG(). You'll know ;-> -All of the above methods are used below, so keep reading for clarity. +All these above nethods are used below. So keep reading for clarity. Device driver changes to be made when porting NAPI ================================================== diff --git a/trunk/Documentation/networking/packet_mmap.txt b/trunk/Documentation/networking/packet_mmap.txt index db0cd5169581..5a232d946be3 100644 --- a/trunk/Documentation/networking/packet_mmap.txt +++ b/trunk/Documentation/networking/packet_mmap.txt @@ -13,7 +13,7 @@ You can find the latest version of this document at Please send me your comments to - Ulisses Alonso Camaró + Ulisses Alonso Camaró ------------------------------------------------------------------------------- + Why use PACKET_MMAP diff --git a/trunk/Documentation/networking/slicecom.hun b/trunk/Documentation/networking/slicecom.hun index bed2f045e550..5acf1918694a 100644 --- a/trunk/Documentation/networking/slicecom.hun +++ b/trunk/Documentation/networking/slicecom.hun @@ -1,7 +1,7 @@ SliceCOM adapter felhasznaloi dokumentacioja - 0.51 verziohoz -Bartók István +Bartók István Utolso modositas: Wed Aug 29 17:26:58 CEST 2001 ----------------------------------------------------------------- diff --git a/trunk/Documentation/networking/slicecom.txt b/trunk/Documentation/networking/slicecom.txt index c82c0cf981b4..32d3b916afad 100644 --- a/trunk/Documentation/networking/slicecom.txt +++ b/trunk/Documentation/networking/slicecom.txt @@ -1,9 +1,9 @@ SliceCOM adapter user's documentation - for the 0.51 driver version -Written by Bartók István +Written by Bartók István -English translation: Lakatos György +English translation: Lakatos György Mon Dec 11 15:28:42 CET 2000 Last modified: Wed Aug 29 17:25:37 CEST 2001 diff --git a/trunk/Documentation/networking/tms380tr.txt b/trunk/Documentation/networking/tms380tr.txt index 1f73e13058df..c169a57bc925 100644 --- a/trunk/Documentation/networking/tms380tr.txt +++ b/trunk/Documentation/networking/tms380tr.txt @@ -71,24 +71,24 @@ Below find attached the setting for the SK NET TR 4/16 ISA adapters CHAPTER 1 LOCATION OF DIP-SWITCH ============================================================== -UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ -þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ -þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ -þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿ -þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ -þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU -þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ -þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿ -þAÄÄÄÄÄÄU þ þ þ þ -þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ -þ þ þ -þ AÄU -þ þ -þ þ -þ þ -þ þ -AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU - AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU +UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ +þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ +þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿ +þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ +þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU +þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ +þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿ +þAÄÄÄÄÄÄU þ þ þ þ +þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ +þ þ þ +þ AÄU +þ þ +þ þ +þ þ +þ þ +AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU + AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU ============================================================== CHAPTER 2 DEFAULT SETTINGS @@ -108,9 +108,9 @@ AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄ CHAPTER 3 DIP SWITCH W1 DESCRIPTION ============================================================== - UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON - þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ - AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF + UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON + þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ + AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF |AD | BootROM Addr. | I/O | +-+-+-------+-------+-----+-----+ | | | diff --git a/trunk/Documentation/networking/udplite.txt b/trunk/Documentation/networking/udplite.txt index 6be09ba24a36..dd6f46b83dab 100644 --- a/trunk/Documentation/networking/udplite.txt +++ b/trunk/Documentation/networking/udplite.txt @@ -139,7 +139,7 @@ 3) Disabling the Checksum Computation On both sender and receiver, checksumming will always be performed - and cannot be disabled using SO_NO_CHECK. Thus + and can not be disabled using SO_NO_CHECK. Thus setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... ); diff --git a/trunk/Documentation/networking/wan-router.txt b/trunk/Documentation/networking/wan-router.txt index bc2ab419a74a..07dd6d9930a1 100644 --- a/trunk/Documentation/networking/wan-router.txt +++ b/trunk/Documentation/networking/wan-router.txt @@ -335,7 +335,7 @@ REVISION HISTORY creating applications using BiSync streaming. -2.0.5 Aug 04, 1999 CHDLC initialization bug fix. +2.0.5 Aug 04, 1999 CHDLC initializatin bug fix. PPP interrupt driven driver: Fix to the PPP line hangup problem. New PPP firmware @@ -372,7 +372,7 @@ REVISION HISTORY o cfgft1 GUI csu/dsu configurator o wancfg GUI configuration file configurator. - o Architectural directory changes. + o Architectual directory changes. beta-2.1.4 Jul 2000 o Dynamic interface configuration: Network interfaces reflect the state diff --git a/trunk/Documentation/pci.txt b/trunk/Documentation/pci.txt index d38261b67905..e2c9d0a0c43d 100644 --- a/trunk/Documentation/pci.txt +++ b/trunk/Documentation/pci.txt @@ -373,7 +373,7 @@ E.g. clearing pending interrupts. 3.6 Register IRQ handler ~~~~~~~~~~~~~~~~~~~~~~~~ -While calling request_irq() is the last step described here, +While calling request_irq() is the the last step described here, this is often just another intermediate step to initialize a device. This step can often be deferred until the device is opened for use. diff --git a/trunk/Documentation/pcieaer-howto.txt b/trunk/Documentation/pcieaer-howto.txt index d5da86170106..16c251230c82 100644 --- a/trunk/Documentation/pcieaer-howto.txt +++ b/trunk/Documentation/pcieaer-howto.txt @@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as well as how to enable the drivers of endpoint devices to conform with PCI Express AER driver. -1.2 Copyright © Intel Corporation 2006. +1.2 Copyright © Intel Corporation 2006. 1.3 What is the PCI Express AER Driver? diff --git a/trunk/Documentation/pnp.txt b/trunk/Documentation/pnp.txt index 481faf515d53..28037aa1846c 100644 --- a/trunk/Documentation/pnp.txt +++ b/trunk/Documentation/pnp.txt @@ -140,7 +140,7 @@ Plug and Play but it is planned to be in the near future. Requirements for a Linux PnP protocol: 1.) the protocol must use EISA IDs 2.) the protocol must inform the PnP Layer of a devices current configuration -- the ability to set resources is optional but preferred. +- the ability to set resources is optional but prefered. The following are PnP protocol related functions: diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index 5b8d6953f05e..c55bd5079b90 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -48,7 +48,7 @@ before suspend (it is limited to 500 MB by default). Article about goals and implementation of Software Suspend for Linux ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Author: G‚ábor Kuti +Author: G‚ábor Kuti Last revised: 2003-10-20 by Pavel Machek Idea and goals to achieve diff --git a/trunk/Documentation/power/userland-swsusp.txt b/trunk/Documentation/power/userland-swsusp.txt index e00c6cf09e85..000556c932e9 100644 --- a/trunk/Documentation/power/userland-swsusp.txt +++ b/trunk/Documentation/power/userland-swsusp.txt @@ -93,23 +93,21 @@ SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to to resume the system from RAM if there's enough battery power or restore its state on the basis of the saved suspend image otherwise) -SNAPSHOT_PMOPS - enable the usage of the hibernation_ops->prepare, - hibernate_ops->enter and hibernation_ops->finish methods (the in-kernel - swsusp knows these as the "platform method") which are needed on many - machines to (among others) speed up the resume by letting the BIOS skip - some steps or to let the system recognise the correct state of the - hardware after the resume (in particular on many machines this ensures - that unplugged AC adapters get correctly detected and that kacpid does - not run wild after the resume). The last ioctl() argument can take one - of the three values, defined in kernel/power/power.h: +SNAPSHOT_PMOPS - enable the usage of the pmops->prepare, pmops->enter and + pmops->finish methods (the in-kernel swsusp knows these as the "platform + method") which are needed on many machines to (among others) speed up + the resume by letting the BIOS skip some steps or to let the system + recognise the correct state of the hardware after the resume (in + particular on many machines this ensures that unplugged AC + adapters get correctly detected and that kacpid does not run wild after + the resume). The last ioctl() argument can take one of the three + values, defined in kernel/power/power.h: PMOPS_PREPARE - make the kernel carry out the - hibernation_ops->prepare() operation + pm_ops->prepare(PM_SUSPEND_DISK) operation PMOPS_ENTER - make the kernel power off the system by calling - hibernation_ops->enter() + pm_ops->enter(PM_SUSPEND_DISK) PMOPS_FINISH - make the kernel carry out the - hibernation_ops->finish() operation - Note that the actual constants are misnamed because they surface - internal kernel implementation details that have changed. + pm_ops->finish(PM_SUSPEND_DISK) operation The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations: diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index b49ce169a63a..d4bfae75c946 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -1444,7 +1444,7 @@ platforms are moved over to use the flattened-device-tree model. Basically, it is a bus of devices, that could act more or less as a complete entity (UCC, USB etc ). All of them should be siblings on the "root" qe node, using the common properties from there. - The description below applies to the qe of MPC8360 and + The description below applies to the the qe of MPC8360 and more nodes and properties would be extended in the future. i) Root QE device @@ -1633,7 +1633,7 @@ platforms are moved over to use the flattened-device-tree model. - assignment : function number of the pin according to the Pin Assignment tables in User Manual. Each pin can have up to 4 possible functions in QE and two options for CPM. - - has_irq : indicates if the pin is used as source of external + - has_irq : indicates if the pin is used as source of exteral interrupts. Example: diff --git a/trunk/Documentation/s390/Debugging390.txt b/trunk/Documentation/s390/Debugging390.txt index d30a281c570f..0993969609cf 100644 --- a/trunk/Documentation/s390/Debugging390.txt +++ b/trunk/Documentation/s390/Debugging390.txt @@ -2209,7 +2209,7 @@ Breakpoint 2 at 0x4d87a4: file top.c, line 2609. #3 0x5167e6 in readline_internal_char () at readline.c:454 #4 0x5168ee in readline_internal_charloop () at readline.c:507 #5 0x51692c in readline_internal () at readline.c:521 -#6 0x5164fe in readline (prompt=0x7ffff810 "\177ÂÿÂøx\177ÂÿÂ÷ÂØ\177ÂÿÂøxÂÀ") +#6 0x5164fe in readline (prompt=0x7ffff810 "\177ÿøx\177ÿ÷Ø\177ÿøxÀ") at readline.c:349 #7 0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1, annotation_suffix=0x4d6b44 "prompt") at top.c:2091 diff --git a/trunk/Documentation/scsi/aacraid.txt b/trunk/Documentation/scsi/aacraid.txt index ce3cb42507bd..2368e7e4a8cf 100644 --- a/trunk/Documentation/scsi/aacraid.txt +++ b/trunk/Documentation/scsi/aacraid.txt @@ -98,8 +98,8 @@ Supported Cards/Chipsets 9005:0285:9005:02b0 (Sunrise Lake ARK) 9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external) 9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote) - 9005:0285:108e:0286 SUN STK RAID INT (Cougar) - 9005:0285:108e:0287 SUN STK RAID EXT (Prometheus) + 9005:0285:108e:0286 SUN SG-XPCIESAS-R-IN (Cougar) + 9005:0285:108e:0287 SUN SG-XPCIESAS-R-EX (Prometheus) People ------------------------- diff --git a/trunk/Documentation/scsi/aha152x.txt b/trunk/Documentation/scsi/aha152x.txt index 29ce6d87e451..2ce022cec9be 100644 --- a/trunk/Documentation/scsi/aha152x.txt +++ b/trunk/Documentation/scsi/aha152x.txt @@ -1,7 +1,7 @@ $Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $ Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x) -Copyright 1993-1999 Jürgen Fischer +Copyright 1993-1999 Jürgen Fischer TC1550 patches by Luuk van Dijk (ldz@xs4all.nl) diff --git a/trunk/Documentation/scsi/aic7xxx.txt b/trunk/Documentation/scsi/aic7xxx.txt index 5f34d2ba69b4..9b894f116d95 100644 --- a/trunk/Documentation/scsi/aic7xxx.txt +++ b/trunk/Documentation/scsi/aic7xxx.txt @@ -40,7 +40,7 @@ The following information is available in this file: 2. Multi-function Twin Channel Device - Two controllers on one chip. 3. Command Channel Secondary DMA Engine - Allows scatter gather list and SCB prefetch. - 4. 64 Byte SCB Support - Allows disconnected, untagged request table + 4. 64 Byte SCB Support - Allows disconnected, unttagged request table for all possible target/lun combinations. 5. Block Move Instruction Support - Doubles the speed of certain sequencer operations. diff --git a/trunk/Documentation/scsi/aic7xxx_old.txt b/trunk/Documentation/scsi/aic7xxx_old.txt index 7bd210ab45a1..05667e7308d4 100644 --- a/trunk/Documentation/scsi/aic7xxx_old.txt +++ b/trunk/Documentation/scsi/aic7xxx_old.txt @@ -356,7 +356,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD or enable Tagged Command Queueing (TCQ) on specific devices. As of driver version 5.1.11, TCQ is now either on or off by default according to the setting you choose during the make config process. - In order to en/disable TCQ for certain devices at boot time, a user + In order to en/disable TCQ for certian devices at boot time, a user may use this boot param. The driver will then parse this message out and en/disable the specific device entries that are present based upon the value given. The param line is parsed in the following manner: diff --git a/trunk/Documentation/scsi/ncr53c8xx.txt b/trunk/Documentation/scsi/ncr53c8xx.txt index 39d409a8efe5..88ef88b949f7 100644 --- a/trunk/Documentation/scsi/ncr53c8xx.txt +++ b/trunk/Documentation/scsi/ncr53c8xx.txt @@ -1260,7 +1260,7 @@ then the request of the IRQ obviously will not succeed for all the drivers. 15.1 Problem tracking Most SCSI problems are due to a non conformant SCSI bus or to buggy -devices. If unfortunately you have SCSI problems, you can check the +devices. If infortunately you have SCSI problems, you can check the following things: - SCSI bus cables diff --git a/trunk/Documentation/scsi/st.txt b/trunk/Documentation/scsi/st.txt index b7be95b5bd24..3c12422f7f41 100644 --- a/trunk/Documentation/scsi/st.txt +++ b/trunk/Documentation/scsi/st.txt @@ -1,5 +1,5 @@ This file contains brief information about the SCSI tape driver. -The driver is currently maintained by Kai Mäkisara (email +The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara diff --git a/trunk/Documentation/scsi/sym53c8xx_2.txt b/trunk/Documentation/scsi/sym53c8xx_2.txt index 3d9f06bb3d00..2c1745a9df00 100644 --- a/trunk/Documentation/scsi/sym53c8xx_2.txt +++ b/trunk/Documentation/scsi/sym53c8xx_2.txt @@ -587,7 +587,7 @@ devices, ... may cause a SCSI signal to be wrong when te driver reads it. 15.1 Problem tracking Most SCSI problems are due to a non conformant SCSI bus or too buggy -devices. If unfortunately you have SCSI problems, you can check the +devices. If infortunately you have SCSI problems, you can check the following things: - SCSI bus cables diff --git a/trunk/Documentation/scsi/tmscsim.txt b/trunk/Documentation/scsi/tmscsim.txt index 61c0531e044a..8b2168aa4fc7 100644 --- a/trunk/Documentation/scsi/tmscsim.txt +++ b/trunk/Documentation/scsi/tmscsim.txt @@ -426,7 +426,7 @@ Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and all the others for the wonderful OS and software. Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver release and support. -Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding. +Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding. Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert Tonneau) for intensively testing the driver (and even risking data loss doing this during early revisions). diff --git a/trunk/Documentation/sonypi.txt b/trunk/Documentation/sonypi.txt index 4857acfc50f1..c1237a925505 100644 --- a/trunk/Documentation/sonypi.txt +++ b/trunk/Documentation/sonypi.txt @@ -1,7 +1,7 @@ Sony Programmable I/O Control Device Driver Readme -------------------------------------------------- Copyright (C) 2001-2004 Stelian Pop - Copyright (C) 2001-2002 Alcôve + Copyright (C) 2001-2002 Alcôve Copyright (C) 2001 Michael Ashley Copyright (C) 2001 Junichi Morita Copyright (C) 2000 Takaya Kinjo diff --git a/trunk/Documentation/sound/oss/mwave b/trunk/Documentation/sound/oss/mwave index 5fbcb1609275..858334bb46b0 100644 --- a/trunk/Documentation/sound/oss/mwave +++ b/trunk/Documentation/sound/oss/mwave @@ -163,7 +163,7 @@ OR the Default= line COULD be Default=SBPRO Reboot to Windows 95 and choose Linux. When booted, use sndconfig to configure -the sound modules and voilà - ThinkPad sound with Linux. +the sound modules and voilà - ThinkPad sound with Linux. Now the gotchas - you can either have CD sound OR Mixers but not both. That's a problem with the SB1.5 (CD sound) or SBPRO (Mixers) settings. No one knows why diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index 111fd28727ec..5922e84d9133 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -221,14 +221,14 @@ Controls the kernel's behaviour when an oops or BUG is encountered. 0: try to continue operation -1: panic immediately. If the `panic' sysctl is also non-zero then the +1: panic immediatly. If the `panic' sysctl is also non-zero then the machine will be rebooted. ============================================================== pid_max: -PID allocation wrap value. When the kernel's next PID value +PID allocation wrap value. When the kenrel's next PID value reaches this value, it wraps back to a minimum PID value. PIDs of value pid_max or larger are not allocated. diff --git a/trunk/Documentation/usb/CREDITS b/trunk/Documentation/usb/CREDITS index 67c59cdc9959..27a721635f92 100644 --- a/trunk/Documentation/usb/CREDITS +++ b/trunk/Documentation/usb/CREDITS @@ -65,7 +65,7 @@ THANKS file in Inaky's driver): will sell keyboards to some of the 3 million (at least) Linux users. - - Many thanks to ing büro h doran [http://www.ibhdoran.com]! + - Many thanks to ing büro h doran [http://www.ibhdoran.com]! It was almost impossible to get a PC backplate USB connector for the motherboard here at Europe (mine, home-made, was quite lousy :). Now I know where to acquire nice USB stuff! diff --git a/trunk/Documentation/usb/usb-serial.txt b/trunk/Documentation/usb/usb-serial.txt index 5b635ae84944..b18e86a22506 100644 --- a/trunk/Documentation/usb/usb-serial.txt +++ b/trunk/Documentation/usb/usb-serial.txt @@ -45,9 +45,9 @@ ConnectTech WhiteHEAT 4 port converter Connect Tech's Support Department at support@connecttech.com -HandSpring Visor, Palm USB, and Clié USB driver +HandSpring Visor, Palm USB, and Clié USB driver - This driver works with all HandSpring USB, Palm USB, and Sony Clié USB + This driver works with all HandSpring USB, Palm USB, and Sony Clié USB devices. Only when the device tries to connect to the host, will the device show @@ -69,7 +69,7 @@ HandSpring Visor, Palm USB, and Clié USB driver the port to use for the HotSync transfer. The "Generic" port can be used for other device communication, such as a PPP link. - For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the + For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the device. This is true for all OS version 3.5 devices, and most devices that have had a flash upgrade to a newer version of the OS. See the kernel system log for information on which is the correct port to use. diff --git a/trunk/Documentation/video4linux/README.pvrusb2 b/trunk/Documentation/video4linux/README.pvrusb2 index a747200fe67c..a4b7ae800866 100644 --- a/trunk/Documentation/video4linux/README.pvrusb2 +++ b/trunk/Documentation/video4linux/README.pvrusb2 @@ -8,7 +8,7 @@ Background: This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which is a USB 2.0 hosted TV Tuner. This driver is a work in progress. - Its history started with the reverse-engineering effort by Björn + Its history started with the reverse-engineering effort by Björn Danielsson whose web page can be found here: http://pvrusb2.dax.nu/ diff --git a/trunk/Documentation/video4linux/Zoran b/trunk/Documentation/video4linux/Zoran index 295462b2317a..85c575ac4fb9 100644 --- a/trunk/Documentation/video4linux/Zoran +++ b/trunk/Documentation/video4linux/Zoran @@ -242,7 +242,7 @@ can generate: PAL , NTSC , SECAM Conexant bt866 TV encoder is used in AVS6EYES, and -can generate: NTSC/PAL, PAL­M, PAL­N +can generate: NTSC/PAL, PAL­M, PAL­N The adv717x, should be able to produce PAL N. But you find nothing PAL N specific in the registers. Seem that you have to reuse a other standard diff --git a/trunk/Documentation/video4linux/meye.txt b/trunk/Documentation/video4linux/meye.txt index bf3af5fe558f..5e51c59bf2b0 100644 --- a/trunk/Documentation/video4linux/meye.txt +++ b/trunk/Documentation/video4linux/meye.txt @@ -1,7 +1,7 @@ Vaio Picturebook Motion Eye Camera Driver Readme ------------------------------------------------ Copyright (C) 2001-2004 Stelian Pop - Copyright (C) 2001-2002 Alcôve + Copyright (C) 2001-2002 Alcôve Copyright (C) 2000 Andrew Tridgell This driver enable the use of video4linux compatible applications with the diff --git a/trunk/Documentation/video4linux/ov511.txt b/trunk/Documentation/video4linux/ov511.txt index b3326b167ada..79af610d4ba5 100644 --- a/trunk/Documentation/video4linux/ov511.txt +++ b/trunk/Documentation/video4linux/ov511.txt @@ -195,11 +195,11 @@ MODULE PARAMETERS: NAME: bandingfilter TYPE: integer (Boolean) DEFAULT: 0 (off) - DESC: Enables the sensor´s banding filter exposure algorithm. This reduces + DESC: Enables the sensor´s banding filter exposure algorithm. This reduces or stabilizes the "banding" caused by some artificial light sources (especially fluorescent). You might have to set lightfreq correctly for this to work right. As an added bonus, this sometimes makes it - possible to capture your monitor´s output. + possible to capture your monitor´s output. NAME: fastset TYPE: integer (Boolean) diff --git a/trunk/Documentation/vm/slabinfo.c b/trunk/Documentation/vm/slabinfo.c index 686a8e04a4f3..41710ccf3a29 100644 --- a/trunk/Documentation/vm/slabinfo.c +++ b/trunk/Documentation/vm/slabinfo.c @@ -16,7 +16,6 @@ #include #include #include -#include #define MAX_SLABS 500 #define MAX_ALIASES 500 @@ -42,15 +41,12 @@ struct aliasinfo { } aliasinfo[MAX_ALIASES]; int slabs = 0; -int actual_slabs = 0; int aliases = 0; int alias_targets = 0; int highest_node = 0; char buffer[4096]; -int show_empty = 0; -int show_report = 0; int show_alias = 0; int show_slab = 0; int skip_zero = 1; @@ -63,15 +59,6 @@ int show_inverted = 0; int show_single_ref = 0; int show_totals = 0; int sort_size = 0; -int set_debug = 0; -int show_ops = 0; - -/* Debug options */ -int sanity = 0; -int redzone = 0; -int poison = 0; -int tracking = 0; -int tracing = 0; int page_size; @@ -89,33 +76,20 @@ void fatal(const char *x, ...) void usage(void) { - printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n" - "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" + printf("slabinfo [-ahnpvtsz] [slab-regexp]\n" "-a|--aliases Show aliases\n" - "-d|--debug= Set/Clear Debug options\n" - "-e|--empty Show empty slabs\n" - "-f|--first-alias Show first alias\n" "-h|--help Show usage information\n" - "-i|--inverted Inverted list\n" - "-l|--slabs Show slabs\n" "-n|--numa Show NUMA information\n" - "-o|--ops Show kmem_cache_ops\n" "-s|--shrink Shrink slabs\n" - "-r|--report Detailed report on single slabs\n" - "-S|--Size Sort by size\n" + "-v|--validate Validate slabs\n" "-t|--tracking Show alloc/free information\n" "-T|--Totals Show summary information\n" - "-v|--validate Validate slabs\n" + "-l|--slabs Show slabs\n" + "-S|--Size Sort by size\n" "-z|--zero Include empty slabs\n" + "-f|--first-alias Show first alias\n" + "-i|--inverted Inverted list\n" "-1|--1ref Single reference\n" - "\nValid debug options (FZPUT may be combined)\n" - "a / A Switch on all debug options (=FZUP)\n" - "- Switch off all debug options\n" - "f / F Sanity Checks (SLAB_DEBUG_FREE)\n" - "z / Z Redzoning\n" - "p / P Poisoning\n" - "u / U Tracking\n" - "t / T Tracing\n" ); } @@ -169,10 +143,11 @@ unsigned long get_obj_and_str(char *name, char **x) void set_obj(struct slabinfo *s, char *name, int n) { char x[100]; - FILE *f; sprintf(x, "%s/%s", s->name, name); - f = fopen(x, "w"); + + FILE *f = fopen(x, "w"); + if (!f) fatal("Cannot write to %s\n", x); @@ -180,26 +155,6 @@ void set_obj(struct slabinfo *s, char *name, int n) fclose(f); } -unsigned long read_slab_obj(struct slabinfo *s, char *name) -{ - char x[100]; - FILE *f; - int l; - - sprintf(x, "%s/%s", s->name, name); - f = fopen(x, "r"); - if (!f) { - buffer[0] = 0; - l = 0; - } else { - l = fread(buffer, 1, sizeof(buffer), f); - buffer[l] = 0; - fclose(f); - } - return l; -} - - /* * Put a size string together */ @@ -271,7 +226,7 @@ int line = 0; void first_line(void) { - printf("Name Objects Objsize Space " + printf("Name Objects Objsize Space " "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); } @@ -291,7 +246,10 @@ struct aliasinfo *find_one_alias(struct slabinfo *find) return best; } } - return best; + if (best) + return best; + fatal("Cannot find alias for %s\n", find->name); + return NULL; } unsigned long slab_size(struct slabinfo *s) @@ -299,126 +257,6 @@ unsigned long slab_size(struct slabinfo *s) return s->slabs * (page_size << s->order); } -void slab_numa(struct slabinfo *s, int mode) -{ - int node; - - if (strcmp(s->name, "*") == 0) - return; - - if (!highest_node) { - printf("\n%s: No NUMA information available.\n", s->name); - return; - } - - if (skip_zero && !s->slabs) - return; - - if (!line) { - printf("\n%-21s:", mode ? "NUMA nodes" : "Slab"); - for(node = 0; node <= highest_node; node++) - printf(" %4d", node); - printf("\n----------------------"); - for(node = 0; node <= highest_node; node++) - printf("-----"); - printf("\n"); - } - printf("%-21s ", mode ? "All slabs" : s->name); - for(node = 0; node <= highest_node; node++) { - char b[20]; - - store_size(b, s->numa[node]); - printf(" %4s", b); - } - printf("\n"); - if (mode) { - printf("%-21s ", "Partial slabs"); - for(node = 0; node <= highest_node; node++) { - char b[20]; - - store_size(b, s->numa_partial[node]); - printf(" %4s", b); - } - printf("\n"); - } - line++; -} - -void show_tracking(struct slabinfo *s) -{ - printf("\n%s: Kernel object allocation\n", s->name); - printf("-----------------------------------------------------------------------\n"); - if (read_slab_obj(s, "alloc_calls")) - printf(buffer); - else - printf("No Data\n"); - - printf("\n%s: Kernel object freeing\n", s->name); - printf("------------------------------------------------------------------------\n"); - if (read_slab_obj(s, "free_calls")) - printf(buffer); - else - printf("No Data\n"); - -} - -void ops(struct slabinfo *s) -{ - if (strcmp(s->name, "*") == 0) - return; - - if (read_slab_obj(s, "ops")) { - printf("\n%s: kmem_cache operations\n", s->name); - printf("--------------------------------------------\n"); - printf(buffer); - } else - printf("\n%s has no kmem_cache operations\n", s->name); -} - -const char *onoff(int x) -{ - if (x) - return "On "; - return "Off"; -} - -void report(struct slabinfo *s) -{ - if (strcmp(s->name, "*") == 0) - return; - printf("\nSlabcache: %-20s Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order); - if (s->hwcache_align) - printf("** Hardware cacheline aligned\n"); - if (s->cache_dma) - printf("** Memory is allocated in a special DMA zone\n"); - if (s->destroy_by_rcu) - printf("** Slabs are destroyed via RCU\n"); - if (s->reclaim_account) - printf("** Reclaim accounting active\n"); - - printf("\nSizes (bytes) Slabs Debug Memory\n"); - printf("------------------------------------------------------------------------\n"); - printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n", - s->object_size, s->slabs, onoff(s->sanity_checks), - s->slabs * (page_size << s->order)); - printf("SlabObj: %7d Full : %7ld Redzoning : %s Used : %7ld\n", - s->slab_size, s->slabs - s->partial - s->cpu_slabs, - onoff(s->red_zone), s->objects * s->object_size); - printf("SlabSiz: %7d Partial: %7ld Poisoning : %s Loss : %7ld\n", - page_size << s->order, s->partial, onoff(s->poison), - s->slabs * (page_size << s->order) - s->objects * s->object_size); - printf("Loss : %7d CpuSlab: %7d Tracking : %s Lalig: %7ld\n", - s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user), - (s->slab_size - s->object_size) * s->objects); - printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n", - s->align, s->objs_per_slab, onoff(s->trace), - ((page_size << s->order) - s->objs_per_slab * s->slab_size) * - s->slabs); - - ops(s); - show_tracking(s); - slab_numa(s, 1); -} void slabcache(struct slabinfo *s) { @@ -427,18 +265,7 @@ void slabcache(struct slabinfo *s) char flags[20]; char *p = flags; - if (strcmp(s->name, "*") == 0) - return; - - if (actual_slabs == 1) { - report(s); - return; - } - - if (skip_zero && !show_empty && !s->slabs) - return; - - if (show_empty && s->slabs) + if (skip_zero && !s->slabs) return; store_size(size_str, slab_size(s)); @@ -476,128 +303,48 @@ void slabcache(struct slabinfo *s) flags); } -/* - * Analyze debug options. Return false if something is amiss. - */ -int debug_opt_scan(char *opt) +void slab_numa(struct slabinfo *s) { - if (!opt || !opt[0] || strcmp(opt, "-") == 0) - return 1; - - if (strcasecmp(opt, "a") == 0) { - sanity = 1; - poison = 1; - redzone = 1; - tracking = 1; - return 1; - } + int node; - for ( ; *opt; opt++) - switch (*opt) { - case 'F' : case 'f': - if (sanity) - return 0; - sanity = 1; - break; - case 'P' : case 'p': - if (poison) - return 0; - poison = 1; - break; + if (!highest_node) + fatal("No NUMA information available.\n"); - case 'Z' : case 'z': - if (redzone) - return 0; - redzone = 1; - break; + if (skip_zero && !s->slabs) + return; - case 'U' : case 'u': - if (tracking) - return 0; - tracking = 1; - break; + if (!line) { + printf("\nSlab Node "); + for(node = 0; node <= highest_node; node++) + printf(" %4d", node); + printf("\n----------------------"); + for(node = 0; node <= highest_node; node++) + printf("-----"); + printf("\n"); + } + printf("%-21s ", s->name); + for(node = 0; node <= highest_node; node++) { + char b[20]; - case 'T' : case 't': - if (tracing) - return 0; - tracing = 1; - break; - default: - return 0; - } - return 1; + store_size(b, s->numa[node]); + printf(" %4s", b); + } + printf("\n"); + line++; } -int slab_empty(struct slabinfo *s) +void show_tracking(struct slabinfo *s) { - if (s->objects > 0) - return 0; - - /* - * We may still have slabs even if there are no objects. Shrinking will - * remove them. - */ - if (s->slabs != 0) - set_obj(s, "shrink", 1); + printf("\n%s: Calls to allocate a slab object\n", s->name); + printf("---------------------------------------------------\n"); + if (read_obj("alloc_calls")) + printf(buffer); - return 1; -} + printf("%s: Calls to free a slab object\n", s->name); + printf("-----------------------------------------------\n"); + if (read_obj("free_calls")) + printf(buffer); -void slab_debug(struct slabinfo *s) -{ - if (sanity && !s->sanity_checks) { - set_obj(s, "sanity", 1); - } - if (!sanity && s->sanity_checks) { - if (slab_empty(s)) - set_obj(s, "sanity", 0); - else - fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); - } - if (redzone && !s->red_zone) { - if (slab_empty(s)) - set_obj(s, "red_zone", 1); - else - fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name); - } - if (!redzone && s->red_zone) { - if (slab_empty(s)) - set_obj(s, "red_zone", 0); - else - fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name); - } - if (poison && !s->poison) { - if (slab_empty(s)) - set_obj(s, "poison", 1); - else - fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name); - } - if (!poison && s->poison) { - if (slab_empty(s)) - set_obj(s, "poison", 0); - else - fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name); - } - if (tracking && !s->store_user) { - if (slab_empty(s)) - set_obj(s, "store_user", 1); - else - fprintf(stderr, "%s not empty cannot enable tracking\n", s->name); - } - if (!tracking && s->store_user) { - if (slab_empty(s)) - set_obj(s, "store_user", 0); - else - fprintf(stderr, "%s not empty cannot disable tracking\n", s->name); - } - if (tracing && !s->trace) { - if (slabs == 1) - set_obj(s, "trace", 1); - else - fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name); - } - if (!tracing && s->trace) - set_obj(s, "trace", 1); } void totals(void) @@ -926,7 +673,7 @@ void link_slabs(void) for (a = aliasinfo; a < aliasinfo + aliases; a++) { - for (s = slabinfo; s < slabinfo + slabs; s++) + for(s = slabinfo; s < slabinfo + slabs; s++) if (strcmp(a->ref, s->name) == 0) { a->slab = s; s->refs++; @@ -957,7 +704,7 @@ void alias(void) continue; } } - printf("\n%-12s <- %s", a->slab->name, a->name); + printf("\n%-20s <- %s", a->slab->name, a->name); active = a->slab->name; } else @@ -982,12 +729,7 @@ void rename_slabs(void) a = find_one_alias(s); - if (a) - s->name = a->name; - else { - s->name = "*"; - actual_slabs--; - } + s->name = a->name; } } @@ -1006,14 +748,11 @@ void read_slab_dir(void) char *t; int count; - if (chdir("/sys/slab")) - fatal("SYSFS support for SLUB not active\n"); - dir = opendir("."); while ((de = readdir(dir))) { if (de->d_name[0] == '.' || - (de->d_name[0] != ':' && slab_mismatch(de->d_name))) - continue; + slab_mismatch(de->d_name)) + continue; switch (de->d_type) { case DT_LNK: alias->name = strdup(de->d_name); @@ -1068,7 +807,6 @@ void read_slab_dir(void) } closedir(dir); slabs = slab - slabinfo; - actual_slabs = slabs; aliases = alias - aliasinfo; if (slabs > MAX_SLABS) fatal("Too many slabs\n"); @@ -1087,37 +825,34 @@ void output_slabs(void) if (show_numa) - slab_numa(slab, 0); - else if (show_track) + slab_numa(slab); + else + if (show_track) show_tracking(slab); - else if (validate) + else + if (validate) slab_validate(slab); - else if (shrink) + else + if (shrink) slab_shrink(slab); - else if (set_debug) - slab_debug(slab); - else if (show_ops) - ops(slab); - else if (show_slab) - slabcache(slab); + else { + if (show_slab) + slabcache(slab); + } } } struct option opts[] = { { "aliases", 0, NULL, 'a' }, - { "debug", 2, NULL, 'd' }, - { "empty", 0, NULL, 'e' }, - { "first-alias", 0, NULL, 'f' }, - { "help", 0, NULL, 'h' }, - { "inverted", 0, NULL, 'i'}, + { "slabs", 0, NULL, 'l' }, { "numa", 0, NULL, 'n' }, - { "ops", 0, NULL, 'o' }, - { "report", 0, NULL, 'r' }, + { "zero", 0, NULL, 'z' }, + { "help", 0, NULL, 'h' }, + { "validate", 0, NULL, 'v' }, + { "first-alias", 0, NULL, 'f' }, { "shrink", 0, NULL, 's' }, - { "slabs", 0, NULL, 'l' }, { "track", 0, NULL, 't'}, - { "validate", 0, NULL, 'v' }, - { "zero", 0, NULL, 'z' }, + { "inverted", 0, NULL, 'i'}, { "1ref", 0, NULL, '1'}, { NULL, 0, NULL, 0 } }; @@ -1129,9 +864,10 @@ int main(int argc, char *argv[]) char *pattern_source; page_size = getpagesize(); + if (chdir("/sys/slab")) + fatal("This kernel does not have SLUB support.\n"); - while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS", - opts, NULL)) != -1) + while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1) switch(c) { case '1': show_single_ref = 1; @@ -1139,14 +875,6 @@ int main(int argc, char *argv[]) case 'a': show_alias = 1; break; - case 'd': - set_debug = 1; - if (!debug_opt_scan(optarg)) - fatal("Invalid debug option '%s'\n", optarg); - break; - case 'e': - show_empty = 1; - break; case 'f': show_first_alias = 1; break; @@ -1159,12 +887,6 @@ int main(int argc, char *argv[]) case 'n': show_numa = 1; break; - case 'o': - show_ops = 1; - break; - case 'r': - show_report = 1; - break; case 's': shrink = 1; break; @@ -1192,8 +914,8 @@ int main(int argc, char *argv[]) } - if (!show_slab && !show_alias && !show_track && !show_report - && !validate && !shrink && !set_debug && !show_ops) + if (!show_slab && !show_alias && !show_track + && !validate && !shrink) show_slab = 1; if (argc > optind) diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index bd558ac5bb73..41a4b477c576 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1038,8 +1038,6 @@ S: Maintained CONEXANT ACCESSRUNNER USB DRIVER P: Simon Arlott M: cxacru@fire.lp0.eu -L: accessrunner-general@lists.sourceforge.net -W: http://accessrunner.sourceforge.net/ S: Maintained CORETEMP HARDWARE MONITORING DRIVER @@ -1718,6 +1716,12 @@ P: H. Peter Anvin M: hpa@zytor.com S: Maintained +i810 TCO TIMER WATCHDOG +P: Nils Faerber +M: nils@kernelconcepts.de +W: http://www.kernelconcepts.de/ +S: Maintained + IA64 (Itanium) PLATFORM P: Tony Luck M: tony.luck@intel.com @@ -2642,12 +2646,6 @@ M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained -ONENAND FLASH DRIVER -P: Kyungmin Park -M: kyungmin.park@samsung.com -L: linux-mtd@lists.infradead.org -S: Maintained - ONSTREAM SCSI TAPE DRIVER P: Willem Riede M: osst@riede.org @@ -2802,7 +2800,7 @@ L: linux-abi-devel@lists.sourceforge.net S: Maintained PHRAM MTD DRIVER -P: Jörn Engel +P: Jörn Engel M: joern@wh.fh-wedel.de L: linux-mtd@lists.infradead.org S: Maintained @@ -3076,7 +3074,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git S: Maintained SCSI TAPE DRIVER -P: Kai Mäkisara +P: Kai Mäkisara M: Kai.Makisara@kolumbus.fi L: linux-scsi@vger.kernel.org S: Maintained diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index d7c0984d4a86..0d8fac3b0371 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -354,7 +354,6 @@ config ARCH_SA1100 config ARCH_S3C2410 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" select GENERIC_GPIO - select GENERIC_TIME help Samsung S3C2410X CPU based systems, such as the Simtec Electronics BAST (), the IPAQ 1940 or diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 00ea4305ad5d..ab9f2d4bd04e 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -47,13 +47,8 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a) arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) -# Only override the compiler option if ARMv6. The ARMv6K extensions are -# always available in ARMv7 -ifeq ($(CONFIG_CPU_32v6),y) arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) -endif arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 diff --git a/trunk/arch/arm/kernel/head-nommu.S b/trunk/arch/arm/kernel/head-nommu.S index 5d78ffb8a9a7..0119c0d5f978 100644 --- a/trunk/arch/arm/kernel/head-nommu.S +++ b/trunk/arch/arm/kernel/head-nommu.S @@ -33,7 +33,7 @@ * numbers for r1. * */ - .section ".text.head", "ax" + __INIT .type stext, %function ENTRY(stext) msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index 41f98b4ba2ee..1d35edacc011 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -73,7 +73,7 @@ * crap here - that's what the boot loader (or in extreme, well justified * circumstances, zImage) is for. */ - .section ".text.head", "ax" + __INIT .type stext, %function ENTRY(stext) msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode diff --git a/trunk/arch/arm/kernel/init_task.c b/trunk/arch/arm/kernel/init_task.c index bd4ef53bc6b9..a00cca0000bd 100644 --- a/trunk/arch/arm/kernel/init_task.c +++ b/trunk/arch/arm/kernel/init_task.c @@ -31,7 +31,7 @@ EXPORT_SYMBOL(init_mm); * The things we do for performance.. */ union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = + __attribute__((__section__(".init.task"))) = { INIT_THREAD_INFO(init_task) }; /* diff --git a/trunk/arch/arm/kernel/module.c b/trunk/arch/arm/kernel/module.c index 79b7e5cf5416..1b061583408e 100644 --- a/trunk/arch/arm/kernel/module.c +++ b/trunk/arch/arm/kernel/module.c @@ -116,8 +116,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset += sym->st_value - loc; if (offset & 3 || - offset <= (s32)0xfe000000 || - offset >= (s32)0x02000000) { + offset <= (s32)0xfc000000 || + offset >= (s32)0x04000000) { printk(KERN_ERR "%s: relocation out of range, section " "%d reloc %d sym '%s'\n", module->name, diff --git a/trunk/arch/arm/kernel/smp.c b/trunk/arch/arm/kernel/smp.c index 1b76d87fa335..070bcb7a6306 100644 --- a/trunk/arch/arm/kernel/smp.c +++ b/trunk/arch/arm/kernel/smp.c @@ -486,7 +486,7 @@ static void ipi_timer(void) } #ifdef CONFIG_LOCAL_TIMERS -asmlinkage void __exception do_local_timer(struct pt_regs *regs) +asmlinkage void do_local_timer(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); int cpu = smp_processor_id(); @@ -551,7 +551,7 @@ static void ipi_cpu_stop(unsigned int cpu) * * Bit 0 - Inter-processor function call */ -asmlinkage void __exception do_IPI(struct pt_regs *regs) +asmlinkage void do_IPI(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct ipi_data *ipi = &per_cpu(ipi_data, cpu); diff --git a/trunk/arch/arm/kernel/vmlinux.lds.S b/trunk/arch/arm/kernel/vmlinux.lds.S index e4156e7868ce..6be67296f333 100644 --- a/trunk/arch/arm/kernel/vmlinux.lds.S +++ b/trunk/arch/arm/kernel/vmlinux.lds.S @@ -23,15 +23,11 @@ SECTIONS #else . = PAGE_OFFSET + TEXT_OFFSET; #endif - .text.head : { - _stext = .; - _sinittext = .; - *(.text.head) - } - .init : { /* Init code and data */ + _stext = .; + _sinittext = .; *(.init.text) - _einittext = .; + _einittext = .; __proc_info_begin = .; *(.proc.info.init) __proc_info_end = .; @@ -123,7 +119,7 @@ SECTIONS * first, the init task union, aligned * to an 8192 byte boundary. */ - *(.data.init_task) + *(.init.task) #ifdef CONFIG_XIP_KERNEL . = ALIGN(4096); diff --git a/trunk/arch/arm/mach-at91/Kconfig b/trunk/arch/arm/mach-at91/Kconfig index 018d637f87fc..e238ad8cfd8f 100644 --- a/trunk/arch/arm/mach-at91/Kconfig +++ b/trunk/arch/arm/mach-at91/Kconfig @@ -107,7 +107,7 @@ config ARCH_AT91SAM9260_SAM9XE depends on ARCH_AT91SAM9260 help Select this if you are using Atmel's AT91SAM9XE System-on-Chip. - They are basically AT91SAM9260s with various sizes of embedded Flash. + They are basicaly AT91SAM9260s with various sizes of embedded Flash. comment "AT91SAM9260 / AT91SAM9XE Board Type" diff --git a/trunk/arch/arm/mach-omap1/Kconfig b/trunk/arch/arm/mach-omap1/Kconfig index 856c681ebbbc..8781aaeb576b 100644 --- a/trunk/arch/arm/mach-omap1/Kconfig +++ b/trunk/arch/arm/mach-omap1/Kconfig @@ -22,7 +22,6 @@ comment "OMAP Board Type" config MACH_OMAP_INNOVATOR bool "TI Innovator" depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) - select OMAP_MCBSP help TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. @@ -30,7 +29,6 @@ config MACH_OMAP_INNOVATOR config MACH_OMAP_H2 bool "TI H2 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select OMAP_MCBSP help TI OMAP 1610/1611B H2 board support. Say Y here if you have such a board. @@ -38,7 +36,6 @@ config MACH_OMAP_H2 config MACH_OMAP_H3 bool "TI H3 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select GPIOEXPANDER_OMAP help TI OMAP 1710 H3 board support. Say Y here if you have such a board. @@ -46,7 +43,7 @@ config MACH_OMAP_H3 config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select OMAP_MCBSP + select TPS65010 help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. @@ -87,7 +84,7 @@ config MACH_OMAP_PALMTE Support for the Palm Tungsten E PDA. Currently only the LCD panel is supported. To boot the kernel, you'll need a PalmOS compatible bootloader; check out http://palmtelinux.sourceforge.net for more - information. + informations. Say Y here if you have such a PDA, say NO otherwise. config MACH_NOKIA770 diff --git a/trunk/arch/arm/mach-omap1/Makefile b/trunk/arch/arm/mach-omap1/Makefile index a8b9a00cea22..7165f74f78da 100644 --- a/trunk/arch/arm/mach-omap1/Makefile +++ b/trunk/arch/arm/mach-omap1/Makefile @@ -37,3 +37,4 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o obj-$(CONFIG_LEDS) += $(led-y) + diff --git a/trunk/arch/arm/mach-omap1/board-fsample.c b/trunk/arch/arm/mach-omap1/board-fsample.c index f65baa95986e..62e42c7a628e 100644 --- a/trunk/arch/arm/mach-omap1/board-fsample.c +++ b/trunk/arch/arm/mach-omap1/board-fsample.c @@ -246,7 +246,7 @@ static void __init fsample_init_smc91x(void) mdelay(50); } -static void __init omap_fsample_init_irq(void) +void omap_fsample_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index 7b260b7c537b..9d2346fb68f4 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -455,7 +455,7 @@ static void __init h3_init_smc91x(void) } } -static void __init h3_init_irq(void) +void h3_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-innovator.c b/trunk/arch/arm/mach-omap1/board-innovator.c index 7e63a41e37c6..cb00530ad279 100644 --- a/trunk/arch/arm/mach-omap1/board-innovator.c +++ b/trunk/arch/arm/mach-omap1/board-innovator.c @@ -308,7 +308,7 @@ static void __init innovator_init_smc91x(void) } } -static void __init innovator_init_irq(void) +void innovator_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-perseus2.c b/trunk/arch/arm/mach-omap1/board-perseus2.c index 1d5c8d509722..fa4be962df67 100644 --- a/trunk/arch/arm/mach-omap1/board-perseus2.c +++ b/trunk/arch/arm/mach-omap1/board-perseus2.c @@ -246,7 +246,7 @@ static void __init perseus2_init_smc91x(void) mdelay(50); } -static void __init omap_perseus2_init_irq(void) +void omap_perseus2_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/devices.c b/trunk/arch/arm/mach-omap1/devices.c index da8a3ac47e13..6dcd10ab4496 100644 --- a/trunk/arch/arm/mach-omap1/devices.c +++ b/trunk/arch/arm/mach-omap1/devices.c @@ -24,6 +24,35 @@ #include #include +#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE) + +static u64 irda_dmamask = 0xffffffff; + +static struct platform_device omap1610ir_device = { + .name = "omap1610-ir", + .id = -1, + .dev = { + .dma_mask = &irda_dmamask, + }, +}; + +static void omap_init_irda(void) +{ + /* FIXME define and use a boot tag, members something like: + * u8 uart; // uart1, or uart3 + * ... but driver only handles uart3 for now + * s16 fir_sel; // gpio for SIR vs FIR + * ... may prefer a callback for SIR/MIR/FIR mode select; + * while h2 uses a GPIO, H3 uses a gpio expander + */ + if (machine_is_omap_h2() + || machine_is_omap_h3()) + (void) platform_device_register(&omap1610ir_device); +} +#else +static inline void omap_init_irda(void) {} +#endif + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) @@ -61,45 +90,6 @@ static void omap_init_rtc(void) static inline void omap_init_rtc(void) {} #endif -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) - -#if defined(CONFIG_ARCH_OMAP15XX) -# define OMAP1_MBOX_SIZE 0x23 -# define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1 -#elif defined(CONFIG_ARCH_OMAP16XX) -# define OMAP1_MBOX_SIZE 0x2f -# define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1 -#endif - -#define OMAP1_MBOX_BASE IO_ADDRESS(OMAP16XX_MAILBOX_BASE) - -static struct resource mbox_resources[] = { - { - .start = OMAP1_MBOX_BASE, - .end = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_DSP_MAILBOX1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mbox_device = { - .name = "mailbox", - .id = -1, - .num_resources = ARRAY_SIZE(mbox_resources), - .resource = mbox_resources, -}; - -static inline void omap_init_mbox(void) -{ - platform_device_register(&mbox_device); -} -#else -static inline void omap_init_mbox(void) { } -#endif - #if defined(CONFIG_OMAP_STI) #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) @@ -164,8 +154,7 @@ static int __init omap1_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - - omap_init_mbox(); + omap_init_irda(); omap_init_rtc(); omap_init_sti(); diff --git a/trunk/arch/arm/mach-omap1/io.c b/trunk/arch/arm/mach-omap1/io.c index 81c4e738506c..fab8b0b27cfb 100644 --- a/trunk/arch/arm/mach-omap1/io.c +++ b/trunk/arch/arm/mach-omap1/io.c @@ -17,11 +17,11 @@ #include #include #include +#include extern int omap1_clk_init(void); extern void omap_check_revision(void); extern void omap_sram_init(void); -extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -121,7 +121,7 @@ void __init omap1_map_common_io(void) #endif omap_sram_init(); - omapfb_reserve_sdram(); + omapfb_reserve_mem(); } /* diff --git a/trunk/arch/arm/mach-omap1/mailbox.c b/trunk/arch/arm/mach-omap1/mailbox.c deleted file mode 100644 index d3abf5609902..000000000000 --- a/trunk/arch/arm/mach-omap1/mailbox.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Mailbox reservation modules for DSP - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * - * 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 -#include -#include -#include -#include -#include - -#define MAILBOX_ARM2DSP1 0x00 -#define MAILBOX_ARM2DSP1b 0x04 -#define MAILBOX_DSP2ARM1 0x08 -#define MAILBOX_DSP2ARM1b 0x0c -#define MAILBOX_DSP2ARM2 0x10 -#define MAILBOX_DSP2ARM2b 0x14 -#define MAILBOX_ARM2DSP1_Flag 0x18 -#define MAILBOX_DSP2ARM1_Flag 0x1c -#define MAILBOX_DSP2ARM2_Flag 0x20 - -unsigned long mbox_base; - -struct omap_mbox1_fifo { - unsigned long cmd; - unsigned long data; - unsigned long flag; -}; - -struct omap_mbox1_priv { - struct omap_mbox1_fifo tx_fifo; - struct omap_mbox1_fifo rx_fifo; -}; - -static inline int mbox_read_reg(unsigned int reg) -{ - return __raw_readw(mbox_base + reg); -} - -static inline void mbox_write_reg(unsigned int val, unsigned int reg) -{ - __raw_writew(val, mbox_base + reg); -} - -/* msg */ -static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; - mbox_msg_t msg; - - msg = mbox_read_reg(fifo->data); - msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; - - return msg; -} - -static inline void -omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; - - mbox_write_reg(msg & 0xffff, fifo->data); - mbox_write_reg(msg >> 16, fifo->cmd); -} - -static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox) -{ - return 0; -} - -static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; - - return (mbox_read_reg(fifo->flag)); -} - -/* irq */ -static inline void -omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_RX) - enable_irq(mbox->irq); -} - -static inline void -omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_RX) - disable_irq(mbox->irq); -} - -static inline int -omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_TX) - return 0; - return 1; -} - -static struct omap_mbox_ops omap1_mbox_ops = { - .type = OMAP_MBOX_TYPE1, - .fifo_read = omap1_mbox_fifo_read, - .fifo_write = omap1_mbox_fifo_write, - .fifo_empty = omap1_mbox_fifo_empty, - .fifo_full = omap1_mbox_fifo_full, - .enable_irq = omap1_mbox_enable_irq, - .disable_irq = omap1_mbox_disable_irq, - .is_irq = omap1_mbox_is_irq, -}; - -/* FIXME: the following struct should be created automatically by the user id */ - -/* DSP */ -static struct omap_mbox1_priv omap1_mbox_dsp_priv = { - .tx_fifo = { - .cmd = MAILBOX_ARM2DSP1b, - .data = MAILBOX_ARM2DSP1, - .flag = MAILBOX_ARM2DSP1_Flag, - }, - .rx_fifo = { - .cmd = MAILBOX_DSP2ARM1b, - .data = MAILBOX_DSP2ARM1, - .flag = MAILBOX_DSP2ARM1_Flag, - }, -}; - -struct omap_mbox mbox_dsp_info = { - .name = "dsp", - .ops = &omap1_mbox_ops, - .priv = &omap1_mbox_dsp_priv, -}; -EXPORT_SYMBOL(mbox_dsp_info); - -static int __init omap1_mbox_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret = 0; - - if (pdev->num_resources != 2) { - dev_err(&pdev->dev, "invalid number of resources: %d\n", - pdev->num_resources); - return -ENODEV; - } - - /* MBOX base */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid mem resource\n"); - return -ENODEV; - } - mbox_base = res->start; - - /* DSP IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_dsp_info.irq = res->start; - - ret = omap_mbox_register(&mbox_dsp_info); - - return ret; -} - -static int omap1_mbox_remove(struct platform_device *pdev) -{ - omap_mbox_unregister(&mbox_dsp_info); - - return 0; -} - -static struct platform_driver omap1_mbox_driver = { - .probe = omap1_mbox_probe, - .remove = omap1_mbox_remove, - .driver = { - .name = "mailbox", - }, -}; - -static int __init omap1_mbox_init(void) -{ - return platform_driver_register(&omap1_mbox_driver); -} - -static void __exit omap1_mbox_exit(void) -{ - platform_driver_unregister(&omap1_mbox_driver); -} - -module_init(omap1_mbox_init); -module_exit(omap1_mbox_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index 7393109f5c30..aab97ccf1e63 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -9,7 +9,6 @@ config ARCH_OMAP2420 bool "OMAP2420 support" depends on ARCH_OMAP24XX select OMAP_DM_TIMER - select ARCH_OMAP_OTG comment "OMAP Board Type" depends on ARCH_OMAP2 @@ -21,7 +20,6 @@ config MACH_OMAP_GENERIC config MACH_OMAP_H4 bool "OMAP 2420 H4 board" depends on ARCH_OMAP2 && ARCH_OMAP24XX - select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG config MACH_OMAP_APOLLON bool "OMAP 2420 Apollon board" diff --git a/trunk/arch/arm/mach-omap2/board-h4.c b/trunk/arch/arm/mach-omap2/board-h4.c index 452193f01531..1e7ed6d22ca9 100644 --- a/trunk/arch/arm/mach-omap2/board-h4.c +++ b/trunk/arch/arm/mach-omap2/board-h4.c @@ -266,26 +266,12 @@ static struct platform_device h4_lcd_device = { .id = -1, }; -static struct resource h4_led_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device h4_led_device = { - .name = "omap_dbg_led", - .id = -1, - .num_resources = ARRAY_SIZE(h4_led_resources), - .resource = h4_led_resources, -}; - static struct platform_device *h4_devices[] __initdata = { &h4_smc91x_device, &h4_flash_device, &h4_irda_device, &h4_kp_device, &h4_lcd_device, - &h4_led_device, }; static inline void __init h4_init_smc91x(void) diff --git a/trunk/arch/arm/mach-omap2/devices.c b/trunk/arch/arm/mach-omap2/devices.c index 52ec2f2d6360..aa4322451e8b 100644 --- a/trunk/arch/arm/mach-omap2/devices.c +++ b/trunk/arch/arm/mach-omap2/devices.c @@ -24,7 +24,7 @@ #include #include -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP2_I2C_BASE2 0x48072000 #define OMAP2_I2C_INT2 57 @@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = { }; static struct platform_device omap_i2c_device2 = { - .name = "i2c_omap", - .id = 2, + .name = "i2c_omap", + .id = 2, .num_resources = ARRAY_SIZE(i2c_resources2), .resource = i2c_resources2, }; @@ -66,40 +66,6 @@ static void omap_init_i2c(void) {} #endif -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) -#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) - -static struct resource mbox_resources[] = { - { - .start = OMAP2_MBOX_BASE, - .end = OMAP2_MBOX_BASE + 0x11f, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_24XX_MAIL_U0_MPU, - .flags = IORESOURCE_IRQ, - }, - { - .start = INT_24XX_MAIL_U3_MPU, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mbox_device = { - .name = "mailbox", - .id = -1, - .num_resources = ARRAY_SIZE(mbox_resources), - .resource = mbox_resources, -}; - -static inline void omap_init_mbox(void) -{ - platform_device_register(&mbox_device); -} -#else -static inline void omap_init_mbox(void) { } -#endif - #if defined(CONFIG_OMAP_STI) #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) @@ -145,45 +111,29 @@ static inline void omap_init_sti(void) {} #define OMAP2_MCSPI1_BASE 0x48098000 #define OMAP2_MCSPI2_BASE 0x4809a000 +/* FIXME: use resources instead */ + static struct omap2_mcspi_platform_config omap2_mcspi1_config = { + .base = io_p2v(OMAP2_MCSPI1_BASE), .num_cs = 4, }; -static struct resource omap2_mcspi1_resources[] = { - { - .start = OMAP2_MCSPI1_BASE, - .end = OMAP2_MCSPI1_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, -}; - struct platform_device omap2_mcspi1 = { .name = "omap2_mcspi", .id = 1, - .num_resources = ARRAY_SIZE(omap2_mcspi1_resources), - .resource = omap2_mcspi1_resources, .dev = { .platform_data = &omap2_mcspi1_config, }, }; static struct omap2_mcspi_platform_config omap2_mcspi2_config = { + .base = io_p2v(OMAP2_MCSPI2_BASE), .num_cs = 2, }; -static struct resource omap2_mcspi2_resources[] = { - { - .start = OMAP2_MCSPI2_BASE, - .end = OMAP2_MCSPI2_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, -}; - struct platform_device omap2_mcspi2 = { .name = "omap2_mcspi", .id = 2, - .num_resources = ARRAY_SIZE(omap2_mcspi2_resources), - .resource = omap2_mcspi2_resources, .dev = { .platform_data = &omap2_mcspi2_config, }, @@ -207,10 +157,10 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_init_i2c(); - omap_init_mbox(); omap_init_mcspi(); omap_init_sti(); return 0; } arch_initcall(omap2_init_devices); + diff --git a/trunk/arch/arm/mach-omap2/gpmc.c b/trunk/arch/arm/mach-omap2/gpmc.c index 54c836a98456..d8f57824423f 100644 --- a/trunk/arch/arm/mach-omap2/gpmc.c +++ b/trunk/arch/arm/mach-omap2/gpmc.c @@ -246,22 +246,14 @@ static int gpmc_cs_mem_enabled(int cs) return l & (1 << 6); } -int gpmc_cs_set_reserved(int cs, int reserved) +static void gpmc_cs_set_reserved(int cs, int reserved) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - gpmc_cs_map &= ~(1 << cs); gpmc_cs_map |= (reserved ? 1 : 0) << cs; - - return 0; } -int gpmc_cs_reserved(int cs) +static int gpmc_cs_reserved(int cs) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - return gpmc_cs_map & (1 << cs); } diff --git a/trunk/arch/arm/mach-omap2/io.c b/trunk/arch/arm/mach-omap2/io.c index 82dc70f6b779..a0728c33e5d9 100644 --- a/trunk/arch/arm/mach-omap2/io.c +++ b/trunk/arch/arm/mach-omap2/io.c @@ -27,7 +27,6 @@ extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); extern void gpmc_init(void); -extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -41,21 +40,9 @@ static struct map_desc omap2_io_desc[] __initdata = { .type = MT_DEVICE }, { - .virtual = DSP_MEM_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), - .length = DSP_MEM_24XX_SIZE, - .type = MT_DEVICE - }, - { - .virtual = DSP_IPI_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), - .length = DSP_IPI_24XX_SIZE, - .type = MT_DEVICE - }, - { - .virtual = DSP_MMU_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), - .length = DSP_MMU_24XX_SIZE, + .virtual = L4_24XX_VIRT, + .pfn = __phys_to_pfn(L4_24XX_PHYS), + .length = L4_24XX_SIZE, .type = MT_DEVICE } }; @@ -73,7 +60,7 @@ void __init omap2_map_common_io(void) omap2_check_revision(); omap_sram_init(); - omapfb_reserve_sdram(); + omapfb_reserve_mem(); } void __init omap2_init_common_hw(void) diff --git a/trunk/arch/arm/mach-omap2/mailbox.c b/trunk/arch/arm/mach-omap2/mailbox.c deleted file mode 100644 index b03cd06e055b..000000000000 --- a/trunk/arch/arm/mach-omap2/mailbox.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Mailbox reservation modules for OMAP2 - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * and Paul Mundt - * - * 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 -#include -#include -#include -#include -#include - -#define MAILBOX_REVISION 0x00 -#define MAILBOX_SYSCONFIG 0x10 -#define MAILBOX_SYSSTATUS 0x14 -#define MAILBOX_MESSAGE_0 0x40 -#define MAILBOX_MESSAGE_1 0x44 -#define MAILBOX_MESSAGE_2 0x48 -#define MAILBOX_MESSAGE_3 0x4c -#define MAILBOX_MESSAGE_4 0x50 -#define MAILBOX_MESSAGE_5 0x54 -#define MAILBOX_FIFOSTATUS_0 0x80 -#define MAILBOX_FIFOSTATUS_1 0x84 -#define MAILBOX_FIFOSTATUS_2 0x88 -#define MAILBOX_FIFOSTATUS_3 0x8c -#define MAILBOX_FIFOSTATUS_4 0x90 -#define MAILBOX_FIFOSTATUS_5 0x94 -#define MAILBOX_MSGSTATUS_0 0xc0 -#define MAILBOX_MSGSTATUS_1 0xc4 -#define MAILBOX_MSGSTATUS_2 0xc8 -#define MAILBOX_MSGSTATUS_3 0xcc -#define MAILBOX_MSGSTATUS_4 0xd0 -#define MAILBOX_MSGSTATUS_5 0xd4 -#define MAILBOX_IRQSTATUS_0 0x100 -#define MAILBOX_IRQENABLE_0 0x104 -#define MAILBOX_IRQSTATUS_1 0x108 -#define MAILBOX_IRQENABLE_1 0x10c -#define MAILBOX_IRQSTATUS_2 0x110 -#define MAILBOX_IRQENABLE_2 0x114 -#define MAILBOX_IRQSTATUS_3 0x118 -#define MAILBOX_IRQENABLE_3 0x11c - -static unsigned long mbox_base; - -#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) -#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) - -struct omap_mbox2_fifo { - unsigned long msg; - unsigned long fifo_stat; - unsigned long msg_stat; -}; - -struct omap_mbox2_priv { - struct omap_mbox2_fifo tx_fifo; - struct omap_mbox2_fifo rx_fifo; - unsigned long irqenable; - unsigned long irqstatus; - u32 newmsg_bit; - u32 notfull_bit; -}; - -static struct clk *mbox_ick_handle; - -static inline unsigned int mbox_read_reg(unsigned int reg) -{ - return __raw_readl(mbox_base + reg); -} - -static inline void mbox_write_reg(unsigned int val, unsigned int reg) -{ - __raw_writel(val, mbox_base + reg); -} - -/* Mailbox H/W preparations */ -static inline int omap2_mbox_startup(struct omap_mbox *mbox) -{ - unsigned int l; - - mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); - if (IS_ERR(mbox_ick_handle)) { - printk("Could not get mailboxes_ick\n"); - return -ENODEV; - } - clk_enable(mbox_ick_handle); - - /* set smart-idle & autoidle */ - l = mbox_read_reg(MAILBOX_SYSCONFIG); - l |= 0x00000011; - mbox_write_reg(l, MAILBOX_SYSCONFIG); - - return 0; -} - -static inline void omap2_mbox_shutdown(struct omap_mbox *mbox) -{ - clk_disable(mbox_ick_handle); - clk_put(mbox_ick_handle); -} - -/* Mailbox FIFO handle functions */ -static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; - return (mbox_msg_t) mbox_read_reg(fifo->msg); -} - -static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; - mbox_write_reg(msg, fifo->msg); -} - -static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; - return (mbox_read_reg(fifo->msg_stat) == 0); -} - -static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; - return (mbox_read_reg(fifo->fifo_stat)); -} - -/* Mailbox IRQ handle functions */ -static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - l = mbox_read_reg(p->irqenable); - l |= bit; - mbox_write_reg(l, p->irqenable); -} - -static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - l = mbox_read_reg(p->irqenable); - l &= ~bit; - mbox_write_reg(l, p->irqenable); -} - -static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - mbox_write_reg(bit, p->irqstatus); -} - -static inline int omap2_mbox_is_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - u32 enable = mbox_read_reg(p->irqenable); - u32 status = mbox_read_reg(p->irqstatus); - - return (enable & status & bit); -} - -static struct omap_mbox_ops omap2_mbox_ops = { - .type = OMAP_MBOX_TYPE2, - .startup = omap2_mbox_startup, - .shutdown = omap2_mbox_shutdown, - .fifo_read = omap2_mbox_fifo_read, - .fifo_write = omap2_mbox_fifo_write, - .fifo_empty = omap2_mbox_fifo_empty, - .fifo_full = omap2_mbox_fifo_full, - .enable_irq = omap2_mbox_enable_irq, - .disable_irq = omap2_mbox_disable_irq, - .ack_irq = omap2_mbox_ack_irq, - .is_irq = omap2_mbox_is_irq, -}; - -/* - * MAILBOX 0: ARM -> DSP, - * MAILBOX 1: ARM <- DSP. - * MAILBOX 2: ARM -> IVA, - * MAILBOX 3: ARM <- IVA. - */ - -/* FIXME: the following structs should be filled automatically by the user id */ - -/* DSP */ -static struct omap_mbox2_priv omap2_mbox_dsp_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE_0, - .fifo_stat = MAILBOX_FIFOSTATUS_0, - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE_1, - .msg_stat = MAILBOX_MSGSTATUS_1, - }, - .irqenable = MAILBOX_IRQENABLE_0, - .irqstatus = MAILBOX_IRQSTATUS_0, - .notfull_bit = MAILBOX_IRQ_NOTFULL(0), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), -}; - -struct omap_mbox mbox_dsp_info = { - .name = "dsp", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_dsp_priv, -}; -EXPORT_SYMBOL(mbox_dsp_info); - -/* IVA */ -static struct omap_mbox2_priv omap2_mbox_iva_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE_2, - .fifo_stat = MAILBOX_FIFOSTATUS_2, - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE_3, - .msg_stat = MAILBOX_MSGSTATUS_3, - }, - .irqenable = MAILBOX_IRQENABLE_3, - .irqstatus = MAILBOX_IRQSTATUS_3, - .notfull_bit = MAILBOX_IRQ_NOTFULL(2), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), -}; - -static struct omap_mbox mbox_iva_info = { - .name = "iva", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_iva_priv, -}; - -static int __init omap2_mbox_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret = 0; - - if (pdev->num_resources != 3) { - dev_err(&pdev->dev, "invalid number of resources: %d\n", - pdev->num_resources); - return -ENODEV; - } - - /* MBOX base */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid mem resource\n"); - return -ENODEV; - } - mbox_base = res->start; - - /* DSP IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_dsp_info.irq = res->start; - - ret = omap_mbox_register(&mbox_dsp_info); - - /* IVA IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_iva_info.irq = res->start; - - ret = omap_mbox_register(&mbox_iva_info); - - return ret; -} - -static int omap2_mbox_remove(struct platform_device *pdev) -{ - omap_mbox_unregister(&mbox_dsp_info); - return 0; -} - -static struct platform_driver omap2_mbox_driver = { - .probe = omap2_mbox_probe, - .remove = omap2_mbox_remove, - .driver = { - .name = "mailbox", - }, -}; - -static int __init omap2_mbox_init(void) -{ - return platform_driver_register(&omap2_mbox_driver); -} - -static void __exit omap2_mbox_exit(void) -{ - platform_driver_unregister(&omap2_mbox_driver); -} - -module_init(omap2_mbox_init); -module_exit(omap2_mbox_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/mach-s3c2410/sleep.S b/trunk/arch/arm/mach-s3c2410/sleep.S index d1eeed2ad47c..637aaba65390 100644 --- a/trunk/arch/arm/mach-s3c2410/sleep.S +++ b/trunk/arch/arm/mach-s3c2410/sleep.S @@ -1,4 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/sleep.S +/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S * * Copyright (c) 2004 Simtec Electronics * Ben Dooks diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index b81391a4e374..e684e9b38216 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -366,19 +366,6 @@ config CPU_32v6K enabled will not boot on processors with do not support these instructions. -# ARMv7 -config CPU_V7 - bool "Support ARM V7 processor" - depends on ARCH_INTEGRATOR - select CPU_32v6K - select CPU_32v7 - select CPU_ABRT_EV7 - select CPU_CACHE_V7 - select CPU_CACHE_VIPT - select CPU_CP15_MMU - select CPU_COPY_V6 if MMU - select CPU_TLB_V6 if MMU - # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. config CPU_32v3 @@ -404,9 +391,6 @@ config CPU_32v5 config CPU_32v6 bool -config CPU_32v7 - bool - # The abort model config CPU_ABRT_NOMMU bool @@ -429,9 +413,6 @@ config CPU_ABRT_EV5TJ config CPU_ABRT_EV6 bool -config CPU_ABRT_EV7 - bool - # The cache model config CPU_CACHE_V3 bool @@ -448,9 +429,6 @@ config CPU_CACHE_V4WB config CPU_CACHE_V6 bool -config CPU_CACHE_V7 - bool - config CPU_CACHE_VIVT bool @@ -525,7 +503,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 default y help Say Y if you want to include kernel support for running user space @@ -600,15 +578,9 @@ config CPU_CACHE_ROUND_ROBIN Say Y here to use the predictable round-robin cache replacement policy. Unless you specifically require this or are unsure, say N. -config CPU_L2CACHE_DISABLE - bool "Disable level 2 cache" - depends on CPU_V7 - help - Say Y here to disable the level 2 cache. If unsure, say N. - config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 + depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/trunk/arch/arm/mm/Makefile b/trunk/arch/arm/mm/Makefile index b5bd335ff14a..2f8b95947774 100644 --- a/trunk/arch/arm/mm/Makefile +++ b/trunk/arch/arm/mm/Makefile @@ -24,14 +24,12 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o -obj-$(CONFIG_CPU_ABRT_EV7) += abort-ev7.o obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o -obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o @@ -68,6 +66,5 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o obj-$(CONFIG_CPU_V6) += proc-v6.o -obj-$(CONFIG_CPU_V7) += proc-v7.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o diff --git a/trunk/arch/arm/mm/abort-ev7.S b/trunk/arch/arm/mm/abort-ev7.S deleted file mode 100644 index eb90bce38e14..000000000000 --- a/trunk/arch/arm/mm/abort-ev7.S +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -/* - * Function: v7_early_abort - * - * Params : r2 = address of aborted instruction - * : r3 = saved SPSR - * - * Returns : r0 = address of abort - * : r1 = FSR, bit 11 = write - * : r2-r8 = corrupted - * : r9 = preserved - * : sp = pointer to registers - * - * Purpose : obtain information about current aborted instruction. - */ - .align 5 -ENTRY(v7_early_abort) - /* - * The effect of data aborts on on the exclusive access monitor are - * UNPREDICTABLE. Do a CLREX to clear the state - */ - clrex - - mrc p15, 0, r1, c5, c0, 0 @ get FSR - mrc p15, 0, r0, c6, c0, 0 @ get FAR - - /* - * V6 code adjusts the returned DFSR. - * New designs should not need to patch up faults. - */ - mov pc, lr diff --git a/trunk/arch/arm/mm/cache-v7.S b/trunk/arch/arm/mm/cache-v7.S deleted file mode 100644 index 35ffc4d95997..000000000000 --- a/trunk/arch/arm/mm/cache-v7.S +++ /dev/null @@ -1,253 +0,0 @@ -/* - * linux/arch/arm/mm/cache-v7.S - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * Copyright (C) 2005 ARM Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This is the "shell" of the ARMv7 processor support. - */ -#include -#include -#include - -#include "proc-macros.S" - -/* - * v7_flush_dcache_all() - * - * Flush the whole D-cache. - * - * Corrupted registers: r0-r5, r7, r9-r11 - * - * - mm - mm_struct describing address space - */ -ENTRY(v7_flush_dcache_all) - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished @ if loc is 0, then no need to clean - mov r10, #0 @ start clean at cache level 0 -loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache level - mov r1, r0, lsr r2 @ extract cache type bits from clidr - and r1, r1, #7 @ mask of the bits for current cache only - cmp r1, #2 @ see what cache we have at this level - blt skip @ skip if no cache, or just i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - isb @ isb to sych the new cssr&csidr - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the way size - clz r5, r4 @ find bit position of way size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop2: - mov r9, r4 @ create working copy of max way size -loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 - mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge loop3 - subs r7, r7, #1 @ decrement the index - bge loop2 -skip: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt loop1 -finished: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - isb - mov pc, lr - -/* - * v7_flush_cache_all() - * - * Flush the entire cache system. - * The data cache flush is now achieved using atomic clean / invalidates - * working outwards from L1 cache. This is done using Set/Way based cache - * maintainance instructions. - * The instruction cache can still be invalidated back to the point of - * unification in a single instruction. - * - */ -ENTRY(v7_flush_kern_cache_all) - stmfd sp!, {r4-r5, r7, r9-r11, lr} - bl v7_flush_dcache_all - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate - ldmfd sp!, {r4-r5, r7, r9-r11, lr} - mov pc, lr - -/* - * v7_flush_cache_all() - * - * Flush all TLB entries in a particular address space - * - * - mm - mm_struct describing address space - */ -ENTRY(v7_flush_user_cache_all) - /*FALLTHROUGH*/ - -/* - * v7_flush_cache_range(start, end, flags) - * - * Flush a range of TLB entries in the specified address space. - * - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - * - flags - vm_area_struct flags describing address space - * - * It is assumed that: - * - we have a VIPT cache. - */ -ENTRY(v7_flush_user_cache_range) - mov pc, lr - -/* - * v7_coherent_kern_range(start,end) - * - * Ensure that the I and D caches are coherent within specified - * region. This is typically used when code has been written to - * a memory region, and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - * - * It is assumed that: - * - the Icache does not read data from the write buffer - */ -ENTRY(v7_coherent_kern_range) - /* FALLTHROUGH */ - -/* - * v7_coherent_user_range(start,end) - * - * Ensure that the I and D caches are coherent within specified - * region. This is typically used when code has been written to - * a memory region, and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - * - * It is assumed that: - * - the Icache does not read data from the write buffer - */ -ENTRY(v7_coherent_user_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: mcr p15, 0, r0, c7, c11, 1 @ clean D line to the point of unification - dsb - mcr p15, 0, r0, c7, c5, 1 @ invalidate I line - add r0, r0, r2 - cmp r0, r1 - blo 1b - mov r0, #0 - mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB - dsb - isb - mov pc, lr - -/* - * v7_flush_kern_dcache_page(kaddr) - * - * Ensure that the data held in the page kaddr is written back - * to the page in question. - * - * - kaddr - kernel address (guaranteed to be page aligned) - */ -ENTRY(v7_flush_kern_dcache_page) - dcache_line_size r2, r3 - add r1, r0, #PAGE_SZ -1: - mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_inv_range(start,end) - * - * Invalidate the data cache within the specified region; we will - * be performing a DMA operation in this region and we want to - * purge old data in the cache. - * - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_inv_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - tst r0, r3 - bic r0, r0, r3 - mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line - - tst r1, r3 - bic r1, r1, r3 - mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line -1: - mcr p15, 0, r0, c7, c6, 1 @ invalidate D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_clean_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_clean_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: - mcr p15, 0, r0, c7, c10, 1 @ clean D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_flush_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_flush_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: - mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - - __INITDATA - - .type v7_cache_fns, #object -ENTRY(v7_cache_fns) - .long v7_flush_kern_cache_all - .long v7_flush_user_cache_all - .long v7_flush_user_cache_range - .long v7_coherent_kern_range - .long v7_coherent_user_range - .long v7_flush_kern_dcache_page - .long v7_dma_inv_range - .long v7_dma_clean_range - .long v7_dma_flush_range - .size v7_cache_fns, . - v7_cache_fns diff --git a/trunk/arch/arm/mm/context.c b/trunk/arch/arm/mm/context.c index fc84fcc74380..9da43a0fdcdf 100644 --- a/trunk/arch/arm/mm/context.c +++ b/trunk/arch/arm/mm/context.c @@ -14,8 +14,7 @@ #include #include -static DEFINE_SPINLOCK(cpu_asid_lock); -unsigned int cpu_last_asid = ASID_FIRST_VERSION; +unsigned int cpu_last_asid = { 1 << ASID_BITS }; /* * We fork()ed a process, and we need a new context for the child @@ -32,16 +31,15 @@ void __new_context(struct mm_struct *mm) { unsigned int asid; - spin_lock(&cpu_asid_lock); asid = ++cpu_last_asid; if (asid == 0) - asid = cpu_last_asid = ASID_FIRST_VERSION; + asid = cpu_last_asid = 1 << ASID_BITS; /* * If we've used up all our ASIDs, we need * to start a new version and flush the TLB. */ - if (unlikely((asid & ~ASID_MASK) == 0)) { + if ((asid & ~ASID_MASK) == 0) { asid = ++cpu_last_asid; /* set the reserved ASID before flushing the TLB */ asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" @@ -49,16 +47,7 @@ void __new_context(struct mm_struct *mm) : "r" (0)); isb(); flush_tlb_all(); - if (icache_is_vivt_asid_tagged()) { - asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" - "mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB\n" - : - : "r" (0)); - dsb(); - } } - spin_unlock(&cpu_asid_lock); - mm->cpu_vm_mask = cpumask_of_cpu(smp_processor_id()); mm->context.id = asid; } diff --git a/trunk/arch/arm/mm/proc-macros.S b/trunk/arch/arm/mm/proc-macros.S index b13150052a76..9e2c89eb2115 100644 --- a/trunk/arch/arm/mm/proc-macros.S +++ b/trunk/arch/arm/mm/proc-macros.S @@ -59,15 +59,3 @@ .word \ucset #endif .endm - -/* - * cache_line_size - get the cache line size from the CSIDR register - * (available on ARMv7+). It assumes that the CSSR register was configured - * to access the L1 data cache CSIDR. - */ - .macro dcache_line_size, reg, tmp - mrc p15, 1, \tmp, c0, c0, 0 @ read CSIDR - and \tmp, \tmp, #7 @ cache line size encoding - mov \reg, #16 @ size offset - mov \reg, \reg, lsl \tmp @ actual cache line size - .endm diff --git a/trunk/arch/arm/mm/proc-v7.S b/trunk/arch/arm/mm/proc-v7.S deleted file mode 100644 index dd823dd4a374..000000000000 --- a/trunk/arch/arm/mm/proc-v7.S +++ /dev/null @@ -1,262 +0,0 @@ -/* - * linux/arch/arm/mm/proc-v7.S - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This is the "shell" of the ARMv7 processor support. - */ -#include -#include -#include -#include -#include -#include - -#include "proc-macros.S" - -#define TTB_C (1 << 0) -#define TTB_S (1 << 1) -#define TTB_RGN_OC_WT (2 << 3) -#define TTB_RGN_OC_WB (3 << 3) - -ENTRY(cpu_v7_proc_init) - mov pc, lr - -ENTRY(cpu_v7_proc_fin) - mov pc, lr - -/* - * cpu_v7_reset(loc) - * - * Perform a soft reset of the system. Put the CPU into the - * same state as it would be if it had been reset, and branch - * to what would be the reset vector. - * - * - loc - location to jump to for soft reset - * - * It is assumed that: - */ - .align 5 -ENTRY(cpu_v7_reset) - mov pc, r0 - -/* - * cpu_v7_do_idle() - * - * Idle the processor (eg, wait for interrupt). - * - * IRQs are already disabled. - */ -ENTRY(cpu_v7_do_idle) - .long 0xe320f003 @ ARM V7 WFI instruction - mov pc, lr - -ENTRY(cpu_v7_dcache_clean_area) -#ifndef TLB_CAN_READ_FROM_L1_CACHE - dcache_line_size r2, r3 -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, r2 - subs r1, r1, r2 - bhi 1b - dsb -#endif - mov pc, lr - -/* - * cpu_v7_switch_mm(pgd_phys, tsk) - * - * Set the translation table base pointer to be pgd_phys - * - * - pgd_phys - physical address of new TTB - * - * It is assumed that: - * - we are not using split page tables - */ -ENTRY(cpu_v7_switch_mm) - mov r2, #0 - ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id - orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB - mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID - isb -1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 - isb - mcr p15, 0, r1, c13, c0, 1 @ set context ID - isb - mov pc, lr - -/* - * cpu_v7_set_pte_ext(ptep, pte) - * - * Set a level 2 translation table entry. - * - * - ptep - pointer to level 2 translation table entry - * (hardware version is stored at -1024 bytes) - * - pte - PTE value to store - * - ext - value for extended PTE bits - * - * Permissions: - * YUWD APX AP1 AP0 SVC User - * 0xxx 0 0 0 no acc no acc - * 100x 1 0 1 r/o no acc - * 10x0 1 0 1 r/o no acc - * 1011 0 0 1 r/w no acc - * 110x 0 1 0 r/w r/o - * 11x0 0 1 0 r/w r/o - * 1111 0 1 1 r/w r/w - */ -ENTRY(cpu_v7_set_pte_ext) - str r1, [r0], #-2048 @ linux version - - bic r3, r1, #0x000003f0 - bic r3, r3, #0x00000003 - orr r3, r3, r2 - orr r3, r3, #PTE_EXT_AP0 | 2 - - tst r1, #L_PTE_WRITE - tstne r1, #L_PTE_DIRTY - orreq r3, r3, #PTE_EXT_APX - - tst r1, #L_PTE_USER - orrne r3, r3, #PTE_EXT_AP1 - tstne r3, #PTE_EXT_APX - bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 - - tst r1, #L_PTE_YOUNG - biceq r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK - - tst r1, #L_PTE_EXEC - orreq r3, r3, #PTE_EXT_XN - - tst r1, #L_PTE_PRESENT - moveq r3, #0 - - str r3, [r0] - mcr p15, 0, r0, c7, c10, 1 @ flush_pte - mov pc, lr - -cpu_v7_name: - .ascii "ARMv7 Processor" - .align - - .section ".text.init", #alloc, #execinstr - -/* - * __v7_setup - * - * Initialise TLB, Caches, and MMU state ready to switch the MMU - * on. Return in r0 the new CP15 C1 control register setting. - * - * We automatically detect if we have a Harvard cache, and use the - * Harvard cache control instructions insead of the unified cache - * control instructions. - * - * This should be able to cover all ARMv7 cores. - * - * It is assumed that: - * - cache type register is implemented - */ -__v7_setup: - adr r12, __v7_setup_stack @ the local stack - stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all - ldmia r12, {r0-r5, r7, r9, r11, lr} - mov r10, #0 -#ifdef HARVARD_CACHE - mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate -#endif - dsb - mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs - mcr p15, 0, r10, c2, c0, 2 @ TTB control register - orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB - mcr p15, 0, r4, c2, c0, 0 @ load TTB0 - mcr p15, 0, r4, c2, c0, 1 @ load TTB1 - mov r10, #0x1f @ domains 0, 1 = manager - mcr p15, 0, r10, c3, c0, 0 @ load domain access register -#ifndef CONFIG_CPU_L2CACHE_DISABLE - @ L2 cache configuration in the L2 aux control register - mrc p15, 1, r10, c9, c0, 2 - bic r10, r10, #(1 << 16) @ L2 outer cache - mcr p15, 1, r10, c9, c0, 2 - @ L2 cache is enabled in the aux control register - mrc p15, 0, r10, c1, c0, 1 - orr r10, r10, #2 - mcr p15, 0, r10, c1, c0, 1 -#endif - mrc p15, 0, r0, c1, c0, 0 @ read control register - ldr r10, cr1_clear @ get mask for bits to clear - bic r0, r0, r10 @ clear bits them - ldr r10, cr1_set @ get mask for bits to set - orr r0, r0, r10 @ set them - mov pc, lr @ return to head.S:__ret - - /* - * V X F I D LR - * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM - * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced - * 0 110 0011 1.00 .111 1101 < we want - */ - .type cr1_clear, #object - .type cr1_set, #object -cr1_clear: - .word 0x0120c302 -cr1_set: - .word 0x00c0387d - -__v7_setup_stack: - .space 4 * 11 @ 11 registers - - .type v7_processor_functions, #object -ENTRY(v7_processor_functions) - .word v7_early_abort - .word cpu_v7_proc_init - .word cpu_v7_proc_fin - .word cpu_v7_reset - .word cpu_v7_do_idle - .word cpu_v7_dcache_clean_area - .word cpu_v7_switch_mm - .word cpu_v7_set_pte_ext - .size v7_processor_functions, . - v7_processor_functions - - .type cpu_arch_name, #object -cpu_arch_name: - .asciz "armv7" - .size cpu_arch_name, . - cpu_arch_name - - .type cpu_elf_name, #object -cpu_elf_name: - .asciz "v7" - .size cpu_elf_name, . - cpu_elf_name - .align - - .section ".proc.info.init", #alloc, #execinstr - - /* - * Match any ARMv7 processor core. - */ - .type __v7_proc_info, #object -__v7_proc_info: - .long 0x000f0000 @ Required ID value - .long 0x000f0000 @ Mask for ID - .long PMD_TYPE_SECT | \ - PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | \ - PMD_SECT_AP_WRITE | \ - PMD_SECT_AP_READ - .long PMD_TYPE_SECT | \ - PMD_SECT_XN | \ - PMD_SECT_AP_WRITE | \ - PMD_SECT_AP_READ - b __v7_setup - .long cpu_arch_name - .long cpu_elf_name - .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_v7_name - .long v7_processor_functions - .long v6wbi_tlb_fns - .long v6_user_fns - .long v7_cache_fns - .size __v7_proc_info, . - __v7_proc_info diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index cfc69f3842fd..9e8d21eca4ec 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -20,11 +20,6 @@ endchoice comment "OMAP Feature Selections" -config OMAP_DEBUG_LEDS - bool - help - For debug card leds on TI reference boards. - config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP @@ -63,14 +58,6 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. -config OMAP_MCBSP - bool "McBSP support" - depends on ARCH_OMAP - default y - help - Say Y here if you want support for the OMAP Multichannel - Buffered Serial Port. - choice prompt "System timer" default OMAP_MPU_TIMER diff --git a/trunk/arch/arm/plat-omap/Makefile b/trunk/arch/arm/plat-omap/Makefile index 41a3c1cf3bd4..2896b4546411 100644 --- a/trunk/arch/arm/plat-omap/Makefile +++ b/trunk/arch/arm/plat-omap/Makefile @@ -3,8 +3,7 @@ # # Common support -obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ - usb.o fb.o +obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o obj-m := obj-n := obj- := @@ -17,4 +16,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o -obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o + diff --git a/trunk/arch/arm/plat-omap/clock.c b/trunk/arch/arm/plat-omap/clock.c index 0a603242f367..f1179ad4be1b 100644 --- a/trunk/arch/arm/plat-omap/clock.c +++ b/trunk/arch/arm/plat-omap/clock.c @@ -33,41 +33,6 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -#ifdef CONFIG_PM_DEBUG - -static void print_parents(struct clk *clk) -{ - struct clk *p; - int printed = 0; - - list_for_each_entry(p, &clocks, node) { - if (p->parent == clk && p->usecount) { - if (!clk->usecount && !printed) { - printk("MISMATCH: %s\n", clk->name); - printed = 1; - } - printk("\t%-15s\n", p->name); - } - } -} - -void clk_print_usecounts(void) -{ - unsigned long flags; - struct clk *p; - - spin_lock_irqsave(&clockfw_lock, flags); - list_for_each_entry(p, &clocks, node) { - if (p->usecount) - printk("%-15s: %d\n", p->name, p->usecount); - print_parents(p); - - } - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -#endif - /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ @@ -284,8 +249,6 @@ void followparent_recalc(struct clk *clk) return; clk->rate = clk->parent->rate; - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /* Propagate rate to children */ diff --git a/trunk/arch/arm/plat-omap/common.c b/trunk/arch/arm/plat-omap/common.c index dd8708ad0a71..fecd3d625995 100644 --- a/trunk/arch/arm/plat-omap/common.c +++ b/trunk/arch/arm/plat-omap/common.c @@ -93,12 +93,8 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) * in the kernel. */ for (i = 0; i < omap_board_config_size; i++) { if (omap_board_config[i].tag == tag) { - if (skip == 0) { - kinfo = &omap_board_config[i]; - break; - } else { - skip--; - } + kinfo = &omap_board_config[i]; + break; } } if (kinfo == NULL) diff --git a/trunk/arch/arm/plat-omap/debug-leds.c b/trunk/arch/arm/plat-omap/debug-leds.c deleted file mode 100644 index 9128a80d228f..000000000000 --- a/trunk/arch/arm/plat-omap/debug-leds.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * linux/arch/arm/plat-omap/debug-leds.c - * - * Copyright 2003 by Texas Instruments Incorporated - * - * 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 -#include - - -/* Many OMAP development platforms reuse the same "debug board"; these - * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the - * debug board (all green), accessed through FPGA registers. - * - * The "surfer" expansion board and H2 sample board also have two-color - * green+red LEDs (in parallel), used here for timer and idle indicators - * in preference to the ones on the debug board, for a "Disco LED" effect. - * - * This driver exports either the original ARM LED API, the new generic - * one, or both. - */ - -static spinlock_t lock; -static struct h2p2_dbg_fpga __iomem *fpga; -static u16 led_state, hw_led_state; - - -#ifdef CONFIG_LEDS_OMAP_DEBUG -#define new_led_api() 1 -#else -#define new_led_api() 0 -#endif - - -/*-------------------------------------------------------------------------*/ - -/* original ARM debug LED API: - * - timer and idle leds (some boards use non-FPGA leds here); - * - up to 4 generic leds, easily accessed in-kernel (any context) - */ - -#define GPIO_LED_RED 3 -#define GPIO_LED_GREEN OMAP_MPUIO(4) - -#define LED_STATE_ENABLED 0x01 -#define LED_STATE_CLAIMED 0x02 -#define LED_TIMER_ON 0x04 - -#define GPIO_IDLE GPIO_LED_GREEN -#define GPIO_TIMER GPIO_LED_RED - -static void h2p2_dbg_leds_event(led_event_t evt) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - if (!(led_state & LED_STATE_ENABLED) && evt != led_start) - goto done; - - switch (evt) { - case led_start: - if (fpga) - led_state |= LED_STATE_ENABLED; - break; - - case led_stop: - case led_halted: - /* all leds off during suspend or shutdown */ - - if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { - omap_set_gpio_dataout(GPIO_TIMER, 0); - omap_set_gpio_dataout(GPIO_IDLE, 0); - } - - __raw_writew(~0, &fpga->leds); - led_state &= ~LED_STATE_ENABLED; - goto done; - - case led_claim: - led_state |= LED_STATE_CLAIMED; - hw_led_state = 0; - break; - - case led_release: - led_state &= ~LED_STATE_CLAIMED; - break; - -#ifdef CONFIG_LEDS_TIMER - case led_timer: - led_state ^= LED_TIMER_ON; - - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; - else { - omap_set_gpio_dataout(GPIO_TIMER, - led_state & LED_TIMER_ON); - goto done; - } - - break; -#endif - -#ifdef CONFIG_LEDS_CPU - /* LED lit iff busy */ - case led_idle_start: - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; - else { - omap_set_gpio_dataout(GPIO_IDLE, 1); - goto done; - } - - break; - - case led_idle_end: - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; - else { - omap_set_gpio_dataout(GPIO_IDLE, 0); - goto done; - } - - break; -#endif - - case led_green_on: - hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; - break; - case led_green_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; - break; - - case led_amber_on: - hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; - break; - case led_amber_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; - break; - - case led_red_on: - hw_led_state |= H2P2_DBG_FPGA_LED_RED; - break; - case led_red_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; - break; - - case led_blue_on: - hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; - break; - case led_blue_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; - break; - - default: - break; - } - - - /* - * Actually burn the LEDs - */ - if (led_state & LED_STATE_ENABLED) - __raw_writew(~hw_led_state, &fpga->leds); - -done: - spin_unlock_irqrestore(&lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -/* "new" LED API - * - with syfs access and generic triggering - * - not readily accessible to in-kernel drivers - */ - -struct dbg_led { - struct led_classdev cdev; - u16 mask; -}; - -static struct dbg_led dbg_leds[] = { - /* REVISIT at least H2 uses different timer & cpu leds... */ -#ifndef CONFIG_LEDS_TIMER - { .mask = 1 << 0, .cdev.name = "d4:green", - .cdev.default_trigger = "heartbeat", }, -#endif -#ifndef CONFIG_LEDS_CPU - { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ -#endif - { .mask = 1 << 2, .cdev.name = "d6:green", }, - { .mask = 1 << 3, .cdev.name = "d7:green", }, - - { .mask = 1 << 4, .cdev.name = "d8:green", }, - { .mask = 1 << 5, .cdev.name = "d9:green", }, - { .mask = 1 << 6, .cdev.name = "d10:green", }, - { .mask = 1 << 7, .cdev.name = "d11:green", }, - - { .mask = 1 << 8, .cdev.name = "d12:green", }, - { .mask = 1 << 9, .cdev.name = "d13:green", }, - { .mask = 1 << 10, .cdev.name = "d14:green", }, - { .mask = 1 << 11, .cdev.name = "d15:green", }, - -#ifndef CONFIG_LEDS - { .mask = 1 << 12, .cdev.name = "d16:green", }, - { .mask = 1 << 13, .cdev.name = "d17:green", }, - { .mask = 1 << 14, .cdev.name = "d18:green", }, - { .mask = 1 << 15, .cdev.name = "d19:green", }, -#endif -}; - -static void -fpga_led_set(struct led_classdev *cdev, enum led_brightness value) -{ - struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - if (value == LED_OFF) - hw_led_state &= ~led->mask; - else - hw_led_state |= led->mask; - __raw_writew(~hw_led_state, &fpga->leds); - spin_unlock_irqrestore(&lock, flags); -} - -static void __init newled_init(struct device *dev) -{ - unsigned i; - struct dbg_led *led; - int status; - - for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { - led->cdev.brightness_set = fpga_led_set; - status = led_classdev_register(dev, &led->cdev); - if (status < 0) - break; - } - return; -} - - -/*-------------------------------------------------------------------------*/ - -static int /* __init */ fpga_probe(struct platform_device *pdev) -{ - struct resource *iomem; - - spin_lock_init(&lock); - - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) - return -ENODEV; - - fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); - __raw_writew(~0, &fpga->leds); - -#ifdef CONFIG_LEDS - leds_event = h2p2_dbg_leds_event; - leds_event(led_start); -#endif - - if (new_led_api()) { - newled_init(&pdev->dev); - } - - return 0; -} - -static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg) -{ - __raw_writew(~0, &fpga->leds); - return 0; -} - -static int fpga_resume_early(struct platform_device *pdev) -{ - __raw_writew(~hw_led_state, &fpga->leds); - return 0; -} - - -static struct platform_driver led_driver = { - .driver.name = "omap_dbg_led", - .probe = fpga_probe, - .suspend_late = fpga_suspend_late, - .resume_early = fpga_resume_early, -}; - -static int __init fpga_init(void) -{ - if (machine_is_omap_h4() - || machine_is_omap_h3() - || machine_is_omap_h2() - || machine_is_omap_perseus2() - ) - return platform_driver_register(&led_driver); - return 0; -} -fs_initcall(fpga_init); diff --git a/trunk/arch/arm/plat-omap/devices.c b/trunk/arch/arm/plat-omap/devices.c index c5dab1d6417e..eeb33fed6f7c 100644 --- a/trunk/arch/arm/plat-omap/devices.c +++ b/trunk/arch/arm/plat-omap/devices.c @@ -25,71 +25,7 @@ #include #include -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) - -#include "../plat-omap/dsp/dsp_common.h" - -static struct dsp_platform_data dsp_pdata = { - .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list), -}; - -static struct resource omap_dsp_resources[] = { - { - .name = "dsp_mmu", - .start = -1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device omap_dsp_device = { - .name = "dsp", - .id = -1, - .num_resources = ARRAY_SIZE(omap_dsp_resources), - .resource = omap_dsp_resources, - .dev = { - .platform_data = &dsp_pdata, - }, -}; - -static inline void omap_init_dsp(void) -{ - struct resource *res; - int irq; - - if (cpu_is_omap15xx()) - irq = INT_1510_DSP_MMU; - else if (cpu_is_omap16xx()) - irq = INT_1610_DSP_MMU; - else if (cpu_is_omap24xx()) - irq = INT_24XX_DSP_MMU; - - res = platform_get_resource_byname(&omap_dsp_device, - IORESOURCE_IRQ, "dsp_mmu"); - res->start = irq; - - platform_device_register(&omap_dsp_device); -} - -int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev) -{ - static DEFINE_MUTEX(dsp_pdata_lock); - - mutex_init(&kdev->lock); - - mutex_lock(&dsp_pdata_lock); - list_add_tail(&kdev->entry, &dsp_pdata.kdev_list); - mutex_unlock(&dsp_pdata_lock); - - return 0; -} -EXPORT_SYMBOL(dsp_kfunc_device_register); - -#else -static inline void omap_init_dsp(void) { } -#endif /* CONFIG_OMAP_DSP */ - -/*-------------------------------------------------------------------------*/ -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP1_I2C_BASE 0xfffb3800 #define OMAP2_I2C_BASE1 0x48070000 @@ -112,8 +48,8 @@ static struct resource i2c_resources1[] = { /* DMA not used; works around erratum writing to non-empty i2c fifo */ static struct platform_device omap_i2c_device1 = { - .name = "i2c_omap", - .id = 1, + .name = "i2c_omap", + .id = 1, .num_resources = ARRAY_SIZE(i2c_resources1), .resource = i2c_resources1, }; @@ -440,7 +376,7 @@ static inline void omap_init_wdt(void) {} /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) +#if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) #ifdef CONFIG_ARCH_OMAP24XX #define OMAP_RNG_BASE 0x480A0000 @@ -500,7 +436,6 @@ static int __init omap_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - omap_init_dsp(); omap_init_i2c(); omap_init_kp(); omap_init_mmc(); @@ -511,3 +446,4 @@ static int __init omap_init_devices(void) return 0; } arch_initcall(omap_init_devices); + diff --git a/trunk/arch/arm/plat-omap/dma.c b/trunk/arch/arm/plat-omap/dma.c index 2d86b106ff3e..f3f84fbf8b87 100644 --- a/trunk/arch/arm/plat-omap/dma.c +++ b/trunk/arch/arm/plat-omap/dma.c @@ -925,17 +925,10 @@ static int omap2_dma_handle_ch(int ch) { u32 status = OMAP_DMA_CSR_REG(ch); - if (!status) { - if (printk_ratelimit()) - printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); + if (!status) return 0; - } - if (unlikely(dma_chan[ch].dev_id == -1)) { - if (printk_ratelimit()) - printk(KERN_WARNING "IRQ %04x for non-allocated DMA" - "channel %d\n", status, ch); + if (unlikely(dma_chan[ch].dev_id == -1)) return 0; - } if (unlikely(status & OMAP_DMA_DROP_IRQ)) printk(KERN_INFO "DMA synchronization event drop occurred with device " @@ -966,15 +959,11 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) int i; val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); - if (val == 0) { - if (printk_ratelimit()) - printk(KERN_WARNING "Spurious DMA IRQ\n"); - return IRQ_HANDLED; - } - for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) { - if (val & 1) - omap2_dma_handle_ch(i); - val >>= 1; + + for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) { + int active = val & (1 << (i - 1)); + if (active) + omap2_dma_handle_ch(i - 1); } return IRQ_HANDLED; diff --git a/trunk/arch/arm/plat-omap/dmtimer.c b/trunk/arch/arm/plat-omap/dmtimer.c index 36073dfaa4db..659619f235ca 100644 --- a/trunk/arch/arm/plat-omap/dmtimer.c +++ b/trunk/arch/arm/plat-omap/dmtimer.c @@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) /* When the functional clock disappears, too quick writes seem to * cause an abort. */ - __delay(150000); + __delay(15000); } #endif diff --git a/trunk/arch/arm/plat-omap/fb.c b/trunk/arch/arm/plat-omap/fb.c index 4493bcff5172..56acb8720f78 100644 --- a/trunk/arch/arm/plat-omap/fb.c +++ b/trunk/arch/arm/plat-omap/fb.c @@ -1,26 +1,3 @@ -/* - * File: arch/arm/plat-omap/fb.c - * - * Framebuffer device registration for TI OMAP platforms - * - * Copyright (C) 2006 Nokia Corporation - * Author: Imre Deak - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the 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 @@ -39,8 +16,6 @@ #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) static struct omapfb_platform_data omapfb_config; -static int config_invalid; -static int configured_regions; static u64 omap_fb_dma_mask = ~(u32)0; @@ -55,270 +30,39 @@ static struct platform_device omap_fb_device = { .num_resources = 0, }; -static inline int ranges_overlap(unsigned long start1, unsigned long size1, - unsigned long start2, unsigned long size2) -{ - return (start1 >= start2 && start1 < start2 + size2) || - (start2 >= start1 && start2 < start1 + size1); -} - -static inline int range_included(unsigned long start1, unsigned long size1, - unsigned long start2, unsigned long size2) -{ - return start1 >= start2 && start1 + size1 <= start2 + size2; -} - - -/* Check if there is an overlapping region. */ -static int fbmem_region_reserved(unsigned long start, size_t size) -{ - struct omapfb_mem_region *rg; - int i; - - rg = &omapfb_config.mem_desc.region[0]; - for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) { - if (!rg->paddr) - /* Empty slot. */ - continue; - if (ranges_overlap(start, size, rg->paddr, rg->size)) - return 1; - } - return 0; -} - -/* - * Get the region_idx`th region from board config/ATAG and convert it to - * our internal format. - */ -static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg) -{ - const struct omap_fbmem_config *conf; - u32 paddr; - - conf = omap_get_nr_config(OMAP_TAG_FBMEM, - struct omap_fbmem_config, region_idx); - if (conf == NULL) - return -ENOENT; - - paddr = conf->start; - /* - * Low bits encode the page allocation mode, if high bits - * are zero. Otherwise we need a page aligned fixed - * address. - */ - memset(rg, 0, sizeof(*rg)); - rg->type = paddr & ~PAGE_MASK; - rg->paddr = paddr & PAGE_MASK; - rg->size = PAGE_ALIGN(conf->size); - return 0; -} - -static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, - unsigned long mem_start, - unsigned long mem_size) -{ - /* - * Check if the configuration specifies the type explicitly. - * type = 0 && paddr = 0, a default don't care case maps to - * the SDRAM type. - */ - if (rg->type || (!rg->type && !rg->paddr)) - return 0; - if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) { - rg->type = mem_type; - return 0; - } - /* Can't determine it. */ - return -1; -} - -static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, - unsigned long start_avail, unsigned size_avail) -{ - unsigned long paddr = rg->paddr; - size_t size = rg->size; - - if (rg->type > OMAPFB_MEMTYPE_MAX) { - printk(KERN_ERR - "Invalid start address for FB region %d\n", region_idx); - return -EINVAL; - } - - if (!rg->size) { - printk(KERN_ERR "Zero size for FB region %d\n", region_idx); - return -EINVAL; - } - - if (!paddr) - /* Allocate this dynamically, leave paddr 0 for now. */ - return 0; - - /* - * Fixed region for the given RAM range. Check if it's already - * reserved by the FB code or someone else. - */ - if (fbmem_region_reserved(paddr, size) || - !range_included(paddr, size, start_avail, size_avail)) { - printk(KERN_ERR "Trying to use reserved memory " - "for FB region %d\n", region_idx); - return -EINVAL; - } - - return 0; -} - -/* - * Called from map_io. We need to call to this early enough so that we - * can reserve the fixed SDRAM regions before VM could get hold of them. - */ -void omapfb_reserve_sdram(void) +/* called from map_io */ +void omapfb_reserve_mem(void) { - struct bootmem_data *bdata; - unsigned long sdram_start, sdram_size; - unsigned long reserved; - int i; - - if (config_invalid) - return; + const struct omap_fbmem_config *fbmem_conf; - bdata = NODE_DATA(0)->bdata; - sdram_start = bdata->node_boot_start; - sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; - reserved = 0; - for (i = 0; ; i++) { - struct omapfb_mem_region rg; + omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; + omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; - if (get_fbmem_region(i, &rg) < 0) - break; - if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR - "Extraneous FB mem configuration entries\n"); - config_invalid = 1; - return; - } - /* Check if it's our memory type. */ - if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM, - sdram_start, sdram_size) < 0 || - (rg.type != OMAPFB_MEMTYPE_SDRAM)) - continue; - BUG_ON(omapfb_config.mem_desc.region[i].size); - if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { - config_invalid = 1; - return; - } - if (rg.paddr) - reserve_bootmem(rg.paddr, rg.size); - reserved += rg.size; - omapfb_config.mem_desc.region[i] = rg; - configured_regions++; - } - omapfb_config.mem_desc.region_cnt = i; - if (reserved) - pr_info("Reserving %lu bytes SDRAM for frame buffer\n", - reserved); -} + fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); -/* - * Called at sram init time, before anything is pushed to the SRAM stack. - * Because of the stack scheme, we will allocate everything from the - * start of the lowest address region to the end of SRAM. This will also - * include padding for page alignment and possible holes between regions. - * - * As opposed to the SDRAM case, we'll also do any dynamic allocations at - * this point, since the driver built as a module would have problem with - * freeing / reallocating the regions. - */ -unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail) -{ - struct omapfb_mem_region rg; - unsigned long pend_avail; - unsigned long reserved; - int i; - - if (config_invalid) - return 0; - - reserved = 0; - pend_avail = pstart_avail + size_avail; - for (i = 0; ; i++) { - if (get_fbmem_region(i, &rg) < 0) - break; - if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR - "Extraneous FB mem configuration entries\n"); - config_invalid = 1; - return 0; - } - - /* Check if it's our memory type. */ - if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM, - sram_pstart, sram_size) < 0 || - (rg.type != OMAPFB_MEMTYPE_SRAM)) - continue; - BUG_ON(omapfb_config.mem_desc.region[i].size); - - if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) { - config_invalid = 1; - return 0; - } - - if (!rg.paddr) { - /* Dynamic allocation */ - if ((size_avail & PAGE_MASK) < rg.size) { - printk("Not enough SRAM for FB region %d\n", - i); - config_invalid = 1; - return 0; - } - size_avail = (size_avail - rg.size) & PAGE_MASK; - rg.paddr = pstart_avail + size_avail; - } - /* Reserve everything above the start of the region. */ - if (pend_avail - rg.paddr > reserved) - reserved = pend_avail - rg.paddr; - size_avail = pend_avail - reserved - pstart_avail; - - /* - * We have a kernel mapping for this already, so the - * driver won't have to make one. + if (fbmem_conf != NULL) { + /* indicate that the bootloader already initialized the + * fb device, so we'll skip that part in the fb driver */ - rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart); - omapfb_config.mem_desc.region[i] = rg; - configured_regions++; + omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; + omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; + if (fbmem_conf->fb_sdram_size) { + pr_info("Reserving %u bytes SDRAM for frame buffer\n", + fbmem_conf->fb_sdram_size); + reserve_bootmem(fbmem_conf->fb_sdram_start, + fbmem_conf->fb_sdram_size); + } } - omapfb_config.mem_desc.region_cnt = i; - if (reserved) - pr_info("Reserving %lu bytes SRAM for frame buffer\n", - reserved); - return reserved; -} - -void omapfb_set_ctrl_platform_data(void *data) -{ - omapfb_config.ctrl_platform_data = data; } static inline int omap_init_fb(void) { const struct omap_lcd_config *conf; - if (config_invalid) - return 0; - if (configured_regions != omapfb_config.mem_desc.region_cnt) { - printk(KERN_ERR "Invalid FB mem configuration entries\n"); - return 0; - } conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); - if (conf == NULL) { - if (configured_regions) - /* FB mem config, but no LCD config? */ - printk(KERN_ERR "Missing LCD configuration\n"); + if (conf == NULL) return 0; - } + omapfb_config.lcd = *conf; return platform_device_register(&omap_fb_device); @@ -328,16 +72,7 @@ arch_initcall(omap_init_fb); #else -void omapfb_reserve_sdram(void) {} -unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long start_avail, - unsigned long size_avail) -{ - return 0; -} - +void omapfb_reserve_mem(void) {} #endif diff --git a/trunk/arch/arm/plat-omap/gpio.c b/trunk/arch/arm/plat-omap/gpio.c index 337455dfe64d..9dc6d3617bdb 100644 --- a/trunk/arch/arm/plat-omap/gpio.c +++ b/trunk/arch/arm/plat-omap/gpio.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -1544,7 +1545,7 @@ void omap2_gpio_resume_after_retention(void) * This may get called early from board specific init * for boards that have interrupts routed via FPGA. */ -int __init omap_gpio_init(void) +int omap_gpio_init(void) { if (!initialized) return _omap_gpio_init(); diff --git a/trunk/arch/arm/plat-omap/mailbox.c b/trunk/arch/arm/plat-omap/mailbox.c deleted file mode 100644 index de7e6ef48bd0..000000000000 --- a/trunk/arch/arm/plat-omap/mailbox.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * OMAP mailbox driver - * - * Copyright (C) 2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * Restructured by Hiroshi DOYU - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mailbox.h" - -static struct omap_mbox *mboxes; -static DEFINE_RWLOCK(mboxes_lock); - -/* Mailbox Sequence Bit function */ -void omap_mbox_init_seq(struct omap_mbox *mbox) -{ - mbox_seq_init(mbox); -} -EXPORT_SYMBOL(omap_mbox_init_seq); - -/* - * message sender - */ -static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) -{ - int ret = 0, i = 1000; - - while (mbox_fifo_full(mbox)) { - if (mbox->ops->type == OMAP_MBOX_TYPE2) - return -1; - if (--i == 0) - return -1; - udelay(1); - } - - if (arg && mbox->txq->callback) { - ret = mbox->txq->callback(arg); - if (ret) - goto out; - } - - mbox_seq_toggle(mbox, &msg); - mbox_fifo_write(mbox, msg); - out: - return ret; -} - -int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) -{ - struct request *rq; - struct request_queue *q = mbox->txq->queue; - int ret = 0; - - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) { - ret = -ENOMEM; - goto fail; - } - - rq->data = (void *)msg; - blk_insert_request(q, rq, 0, arg); - - schedule_work(&mbox->txq->work); - fail: - return ret; -} -EXPORT_SYMBOL(omap_mbox_msg_send); - -static void mbox_tx_work(struct work_struct *work) -{ - int ret; - struct request *rq; - struct omap_mbox_queue *mq = container_of(work, - struct omap_mbox_queue, work); - struct omap_mbox *mbox = mq->queue->queuedata; - struct request_queue *q = mbox->txq->queue; - - while (1) { - spin_lock(q->queue_lock); - rq = elv_next_request(q); - spin_unlock(q->queue_lock); - - if (!rq) - break; - - ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); - if (ret) { - enable_mbox_irq(mbox, IRQ_TX); - return; - } - - spin_lock(q->queue_lock); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock(q->queue_lock); - } -} - -/* - * Message receiver(workqueue) - */ -static void mbox_rx_work(struct work_struct *work) -{ - struct omap_mbox_queue *mq = - container_of(work, struct omap_mbox_queue, work); - struct omap_mbox *mbox = mq->queue->queuedata; - struct request_queue *q = mbox->rxq->queue; - struct request *rq; - mbox_msg_t msg; - unsigned long flags; - - if (mbox->rxq->callback == NULL) { - sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); - return; - } - - while (1) { - spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - spin_unlock_irqrestore(q->queue_lock, flags); - if (!rq) - break; - - msg = (mbox_msg_t) rq->data; - - spin_lock_irqsave(q->queue_lock, flags); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - - mbox->rxq->callback((void *)msg); - } -} - -/* - * Mailbox interrupt handler - */ -static void mbox_txq_fn(request_queue_t * q) -{ -} - -static void mbox_rxq_fn(request_queue_t * q) -{ -} - -static void __mbox_tx_interrupt(struct omap_mbox *mbox) -{ - disable_mbox_irq(mbox, IRQ_TX); - ack_mbox_irq(mbox, IRQ_TX); - schedule_work(&mbox->txq->work); -} - -static void __mbox_rx_interrupt(struct omap_mbox *mbox) -{ - struct request *rq; - mbox_msg_t msg; - request_queue_t *q = mbox->rxq->queue; - - disable_mbox_irq(mbox, IRQ_RX); - - while (!mbox_fifo_empty(mbox)) { - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) - goto nomem; - - msg = mbox_fifo_read(mbox); - rq->data = (void *)msg; - - if (unlikely(mbox_seq_test(mbox, msg))) { - pr_info("mbox: Illegal seq bit!(%08x)\n", msg); - if (mbox->err_notify) - mbox->err_notify(); - } - - blk_insert_request(q, rq, 0, NULL); - if (mbox->ops->type == OMAP_MBOX_TYPE1) - break; - } - - /* no more messages in the fifo. clear IRQ source. */ - ack_mbox_irq(mbox, IRQ_RX); - enable_mbox_irq(mbox, IRQ_RX); - nomem: - schedule_work(&mbox->rxq->work); -} - -static irqreturn_t mbox_interrupt(int irq, void *p) -{ - struct omap_mbox *mbox = (struct omap_mbox *)p; - - if (is_mbox_irq(mbox, IRQ_TX)) - __mbox_tx_interrupt(mbox); - - if (is_mbox_irq(mbox, IRQ_RX)) - __mbox_rx_interrupt(mbox); - - return IRQ_HANDLED; -} - -/* - * sysfs files - */ -static ssize_t -omap_mbox_write(struct device *dev, struct device_attribute *attr, - const char * buf, size_t count) -{ - int ret; - mbox_msg_t *p = (mbox_msg_t *)buf; - struct omap_mbox *mbox = dev_get_drvdata(dev); - - for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { - ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); - if (ret) - return -EAGAIN; - p++; - } - - return (size_t)((char *)p - buf); -} - -static ssize_t -omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) -{ - unsigned long flags; - struct request *rq; - mbox_msg_t *p = (mbox_msg_t *) buf; - struct omap_mbox *mbox = dev_get_drvdata(dev); - struct request_queue *q = mbox->rxq->queue; - - while (1) { - spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (!rq) - break; - - *p = (mbox_msg_t) rq->data; - - spin_lock_irqsave(q->queue_lock, flags); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (unlikely(mbox_seq_test(mbox, *p))) { - pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); - continue; - } - p++; - } - - pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); - - return (size_t) ((char *)p - buf); -} - -static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); - -static ssize_t mbox_show(struct class *class, char *buf) -{ - return sprintf(buf, "mbox"); -} - -static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); - -static struct class omap_mbox_class = { - .name = "omap_mbox", -}; - -static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, - request_fn_proc * proc, - void (*work) (struct work_struct *)) -{ - request_queue_t *q; - struct omap_mbox_queue *mq; - - mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); - if (!mq) - return NULL; - - spin_lock_init(&mq->lock); - - q = blk_init_queue(proc, &mq->lock); - if (!q) - goto error; - q->queuedata = mbox; - mq->queue = q; - - INIT_WORK(&mq->work, work); - - return mq; -error: - kfree(mq); - return NULL; -} - -static void mbox_queue_free(struct omap_mbox_queue *q) -{ - blk_cleanup_queue(q->queue); - kfree(q); -} - -static int omap_mbox_init(struct omap_mbox *mbox) -{ - int ret; - struct omap_mbox_queue *mq; - - if (likely(mbox->ops->startup)) { - ret = mbox->ops->startup(mbox); - if (unlikely(ret)) - return ret; - } - - mbox->dev.class = &omap_mbox_class; - strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); - dev_set_drvdata(&mbox->dev, mbox); - - ret = device_register(&mbox->dev); - if (unlikely(ret)) - goto fail_device_reg; - - ret = device_create_file(&mbox->dev, &dev_attr_mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "device_create_file failed: %d\n", ret); - goto fail_create_mbox; - } - - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, - mbox->name, mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "failed to register mailbox interrupt:%d\n", ret); - goto fail_request_irq; - } - enable_mbox_irq(mbox, IRQ_RX); - - mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_txq; - } - mbox->txq = mq; - - mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_rxq; - } - mbox->rxq = mq; - - return 0; - - fail_alloc_rxq: - mbox_queue_free(mbox->txq); - fail_alloc_txq: - free_irq(mbox->irq, mbox); - fail_request_irq: - device_remove_file(&mbox->dev, &dev_attr_mbox); - fail_create_mbox: - device_unregister(&mbox->dev); - fail_device_reg: - if (unlikely(mbox->ops->shutdown)) - mbox->ops->shutdown(mbox); - - return ret; -} - -static void omap_mbox_fini(struct omap_mbox *mbox) -{ - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); - - free_irq(mbox->irq, mbox); - device_remove_file(&mbox->dev, &dev_attr_mbox); - class_unregister(&omap_mbox_class); - - if (unlikely(mbox->ops->shutdown)) - mbox->ops->shutdown(mbox); -} - -static struct omap_mbox **find_mboxes(const char *name) -{ - struct omap_mbox **p; - - for (p = &mboxes; *p; p = &(*p)->next) { - if (strcmp((*p)->name, name) == 0) - break; - } - - return p; -} - -struct omap_mbox *omap_mbox_get(const char *name) -{ - struct omap_mbox *mbox; - int ret; - - read_lock(&mboxes_lock); - mbox = *(find_mboxes(name)); - if (mbox == NULL) { - read_unlock(&mboxes_lock); - return ERR_PTR(-ENOENT); - } - - read_unlock(&mboxes_lock); - - ret = omap_mbox_init(mbox); - if (ret) - return ERR_PTR(-ENODEV); - - return mbox; -} -EXPORT_SYMBOL(omap_mbox_get); - -void omap_mbox_put(struct omap_mbox *mbox) -{ - omap_mbox_fini(mbox); -} -EXPORT_SYMBOL(omap_mbox_put); - -int omap_mbox_register(struct omap_mbox *mbox) -{ - int ret = 0; - struct omap_mbox **tmp; - - if (!mbox) - return -EINVAL; - if (mbox->next) - return -EBUSY; - - write_lock(&mboxes_lock); - tmp = find_mboxes(mbox->name); - if (*tmp) - ret = -EBUSY; - else - *tmp = mbox; - write_unlock(&mboxes_lock); - - return ret; -} -EXPORT_SYMBOL(omap_mbox_register); - -int omap_mbox_unregister(struct omap_mbox *mbox) -{ - struct omap_mbox **tmp; - - write_lock(&mboxes_lock); - tmp = &mboxes; - while (*tmp) { - if (mbox == *tmp) { - *tmp = mbox->next; - mbox->next = NULL; - write_unlock(&mboxes_lock); - return 0; - } - tmp = &(*tmp)->next; - } - write_unlock(&mboxes_lock); - - return -EINVAL; -} -EXPORT_SYMBOL(omap_mbox_unregister); - -static int __init omap_mbox_class_init(void) -{ - int ret = class_register(&omap_mbox_class); - if (!ret) - ret = class_create_file(&omap_mbox_class, &class_attr_mbox); - - return ret; -} - -static void __exit omap_mbox_class_exit(void) -{ - class_remove_file(&omap_mbox_class, &class_attr_mbox); - class_unregister(&omap_mbox_class); -} - -subsys_initcall(omap_mbox_class_init); -module_exit(omap_mbox_class_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/plat-omap/mailbox.h b/trunk/arch/arm/plat-omap/mailbox.h deleted file mode 100644 index 67c6740b8ad5..000000000000 --- a/trunk/arch/arm/plat-omap/mailbox.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Mailbox internal functions - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * - * 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. - */ - -#ifndef __ARCH_ARM_PLAT_MAILBOX_H -#define __ARCH_ARM_PLAT_MAILBOX_H - -/* - * Mailbox sequence bit API - */ -#if defined(CONFIG_ARCH_OMAP1) -# define MBOX_USE_SEQ_BIT -#elif defined(CONFIG_ARCH_OMAP2) -# define MBOX_USE_SEQ_BIT -#endif - -#ifdef MBOX_USE_SEQ_BIT -/* seq_rcv should be initialized with any value other than - * 0 and 1 << 31, to allow either value for the first - * message. */ -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ - /* any value other than 0 and 1 << 31 */ - mbox->seq_rcv = 0xffffffff; -} - -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ - /* add seq_snd to msg */ - *msg = (*msg & 0x7fffffff) | mbox->seq_snd; - /* flip seq_snd */ - mbox->seq_snd ^= 1 << 31; -} - -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox_msg_t seq = msg & (1 << 31); - if (seq == mbox->seq_rcv) - return -1; - mbox->seq_rcv = seq; - return 0; -} -#else -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ -} -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ -} -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - return 0; -} -#endif - -/* Mailbox FIFO handle functions */ -static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_read(mbox); -} -static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox->ops->fifo_write(mbox, msg); -} -static inline int mbox_fifo_empty(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_empty(mbox); -} -static inline int mbox_fifo_full(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_full(mbox); -} - -/* Mailbox IRQ handle functions */ -static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->enable_irq(mbox, irq); -} -static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->disable_irq(mbox, irq); -} -static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - if (mbox->ops->ack_irq) - mbox->ops->ack_irq(mbox, irq); -} -static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - return mbox->ops->is_irq(mbox, irq); -} - -#endif /* __ARCH_ARM_PLAT_MAILBOX_H */ diff --git a/trunk/arch/arm/plat-omap/sram.c b/trunk/arch/arm/plat-omap/sram.c index bc46f33aede3..19014b2ff4c6 100644 --- a/trunk/arch/arm/plat-omap/sram.c +++ b/trunk/arch/arm/plat-omap/sram.c @@ -46,19 +46,14 @@ #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) -static unsigned long omap_sram_start; static unsigned long omap_sram_base; static unsigned long omap_sram_size; static unsigned long omap_sram_ceil; -extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail); +unsigned long omap_fb_sram_start; +unsigned long omap_fb_sram_size; -/* - * Depending on the target RAMFS firewall setup, the public usable amount of +/* Depending on the target RAMFS firewall setup, the public usable amount of * SRAM varies. The default accessable size for all device types is 2k. A GP * device allows ARM11 but not other initators for full size. This * functionality seems ok until some nice security API happens. @@ -82,6 +77,32 @@ static int is_sram_locked(void) return 1; /* assume locked with no PPA or security driver */ } +void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, + unsigned long *start, unsigned long *size) +{ + const struct omap_fbmem_config *fbmem_conf; + + fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); + if (fbmem_conf != NULL) { + *start = fbmem_conf->fb_sram_start; + *size = fbmem_conf->fb_sram_size; + } else { + *size = 0; + *start = 0; + } + + if (*size && ( + *start < start_avail || + *start + *size > start_avail + size_avail)) { + printk(KERN_ERR "invalid FB SRAM configuration\n"); + *start = start_avail; + *size = size_avail; + } + + if (*size) + pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); +} + /* * The amount of SRAM depends on the core type. * Note that we cannot try to test for SRAM here because writes @@ -90,16 +111,16 @@ static int is_sram_locked(void) */ void __init omap_detect_sram(void) { - unsigned long reserved; + unsigned long sram_start; if (cpu_is_omap24xx()) { if (is_sram_locked()) { omap_sram_base = OMAP2_SRAM_PUB_VA; - omap_sram_start = OMAP2_SRAM_PUB_PA; + sram_start = OMAP2_SRAM_PUB_PA; omap_sram_size = 0x800; /* 2K */ } else { omap_sram_base = OMAP2_SRAM_VA; - omap_sram_start = OMAP2_SRAM_PA; + sram_start = OMAP2_SRAM_PA; if (cpu_is_omap242x()) omap_sram_size = 0xa0000; /* 640K */ else if (cpu_is_omap243x()) @@ -107,7 +128,7 @@ void __init omap_detect_sram(void) } } else { omap_sram_base = OMAP1_SRAM_VA; - omap_sram_start = OMAP1_SRAM_PA; + sram_start = OMAP1_SRAM_PA; if (cpu_is_omap730()) omap_sram_size = 0x32000; /* 200K */ @@ -123,11 +144,12 @@ void __init omap_detect_sram(void) omap_sram_size = 0x4000; } } - reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base, - omap_sram_size, - omap_sram_start + SRAM_BOOTLOADER_SZ, - omap_sram_size - SRAM_BOOTLOADER_SZ); - omap_sram_size -= reserved; + get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ, + &omap_fb_sram_start, &omap_fb_sram_size); + if (omap_fb_sram_size) + omap_sram_size -= sram_start + omap_sram_size - + omap_fb_sram_start; omap_sram_ceil = omap_sram_base + omap_sram_size; } diff --git a/trunk/arch/arm/plat-omap/usb.c b/trunk/arch/arm/plat-omap/usb.c index 25489aafb113..7e8096809be2 100644 --- a/trunk/arch/arm/plat-omap/usb.c +++ b/trunk/arch/arm/plat-omap/usb.c @@ -37,27 +37,9 @@ #include #include -#ifdef CONFIG_ARCH_OMAP1 - -#define INT_USB_IRQ_GEN IH2_BASE + 20 -#define INT_USB_IRQ_NISO IH2_BASE + 30 -#define INT_USB_IRQ_ISO IH2_BASE + 29 -#define INT_USB_IRQ_HGEN INT_USB_HHC_1 -#define INT_USB_IRQ_OTG IH2_BASE + 8 - -#else - -#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN -#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO -#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO -#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN -#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG - -#endif - - /* These routines should handle the standard chip-specific modes * for usb0/1/2 ports, covering basic mux and transceiver setup. + * Call omap_usb_init() once, from INIT_MACHINE(). * * Some board-*.c files will need to set up additional mux options, * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. @@ -114,26 +96,19 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); - if (nwires == 0) { - if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { + if (!cpu_is_omap15xx()) { /* pulldown D+/D- */ USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); } return 0; } - if (is_device) { - if (cpu_is_omap24xx()) - omap_cfg_reg(J20_24XX_USB0_PUEN); - else - omap_cfg_reg(W4_USB_PUEN); - } + if (is_device) + omap_cfg_reg(W4_USB_PUEN); - /* internal transceiver (unavailable on 17xx, 24xx) */ - if (!cpu_class_is_omap2() && nwires == 2) { + /* internal transceiver */ + if (nwires == 2) { // omap_cfg_reg(P9_USB_DP); // omap_cfg_reg(R8_USB_DM); @@ -161,50 +136,29 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return 0; } - if (cpu_is_omap24xx()) { - omap_cfg_reg(K18_24XX_USB0_DAT); - omap_cfg_reg(K19_24XX_USB0_TXEN); - omap_cfg_reg(J14_24XX_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(J18_24XX_USB0_RCV); - } else { - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - } + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(W5_USB0_SE0); - /* NOTE: SPEED and SUSP aren't configured here. OTG hosts - * may be able to use I2C requests to set those bits along - * with VBUS switching and overcurrent detction. - */ + /* NOTE: SPEED and SUSP aren't configured here */ - if (cpu_class_is_omap1() && nwires != 6) + if (nwires != 3) + omap_cfg_reg(Y5_USB0_RCV); + if (nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; switch (nwires) { case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 6: syscon1 = 3; - if (cpu_is_omap24xx()) { - omap_cfg_reg(J19_24XX_USB0_VP); - omap_cfg_reg(K20_24XX_USB0_VM); - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); - } else { - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; - } + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(R9_USB0_VM); + USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -217,22 +171,14 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); - if (nwires == 0) return 0; /* external transceiver */ - if (cpu_class_is_omap1()) { - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); - if (nwires != 3) - omap_cfg_reg(USB1_RCV); - } - + omap_cfg_reg(USB1_TXD); + omap_cfg_reg(USB1_TXEN); if (cpu_is_omap15xx()) { omap_cfg_reg(USB1_SEO); omap_cfg_reg(USB1_SPEED); @@ -244,38 +190,20 @@ static u32 __init omap_usb1_init(unsigned nwires) } else if (cpu_is_omap1710()) { omap_cfg_reg(R13_1710_USB1_SE0); // SUSP - } else if (cpu_is_omap24xx()) { - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; + pr_debug("usb unrecognized\n"); } + if (nwires != 3) + omap_cfg_reg(USB1_RCV); switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); - break; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); @@ -283,7 +211,6 @@ static u32 __init omap_usb1_init(unsigned nwires) USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; break; default: -bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 1, nwires); } @@ -294,17 +221,10 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) { - CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) - | USBT2TLL5PI); - alt_pingroup = 0; - } - - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ + /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; - - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; /* external transceiver */ @@ -322,54 +242,19 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) if (nwires != 3) omap_cfg_reg(Y5_USB2_RCV); // FIXME omap_cfg_reg(USB2_SPEED); - } else if (cpu_is_omap24xx()) { - omap_cfg_reg(Y11_24XX_USB2_DAT); - omap_cfg_reg(AA10_24XX_USB2_SE0); - if (nwires > 2) - omap_cfg_reg(AA12_24XX_USB2_TXEN); - if (nwires > 3) - omap_cfg_reg(AA6_24XX_USB2_RCV); } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; + pr_debug("usb unrecognized\n"); } - // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); + // omap_cfg_reg(USB2_SUSP); switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); - break; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); - break; - case 5: - if (!cpu_is_omap24xx()) - goto bad; - omap_cfg_reg(AA4_24XX_USB2_TLLSE0); - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - */ - syscon1 = 3; - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) - | USBT2TLL5PI; break; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); @@ -381,7 +266,6 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) } break; default: -bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 2, nwires); } @@ -410,13 +294,13 @@ static struct resource udc_resources[] = { .end = UDC_BASE + 0xff, .flags = IORESOURCE_MEM, }, { /* general IRQ */ - .start = INT_USB_IRQ_GEN, + .start = IH2_BASE + 20, .flags = IORESOURCE_IRQ, }, { /* PIO IRQ */ - .start = INT_USB_IRQ_NISO, + .start = IH2_BASE + 30, .flags = IORESOURCE_IRQ, }, { /* SOF IRQ */ - .start = INT_USB_IRQ_ISO, + .start = IH2_BASE + 29, .flags = IORESOURCE_IRQ, }, }; @@ -445,11 +329,11 @@ static u64 ohci_dmamask = ~(u32)0; static struct resource ohci_resources[] = { { .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 0xff, + .end = OMAP_OHCI_BASE + 4096 - 1, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_IRQ_HGEN, + .start = INT_USB_HHC_1, .flags = IORESOURCE_IRQ, }, }; @@ -477,7 +361,7 @@ static struct resource otg_resources[] = { .end = OTG_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_IRQ_OTG, + .start = IH2_BASE + 8, .flags = IORESOURCE_IRQ, }, }; @@ -501,7 +385,7 @@ static struct platform_device otg_device = { // FIXME correct answer depends on hmc_mode, -// as does (on omap1) any nonzero value for config->otg port number +// as does any nonzero value for config->otg port number #ifdef CONFIG_USB_GADGET_OMAP #define is_usb0_device(config) 1 #else @@ -542,13 +426,12 @@ omap_otg_init(struct omap_usb_config *config) if (config->otg) syscon |= OTG_EN; #endif - if (cpu_class_is_omap1()) - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); + pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); OTG_SYSCON_2_REG = syscon; printk("USB: hmc %d", config->hmc_mode); - if (!alt_pingroup) + if (alt_pingroup) printk(", usb2 alt %d wires", config->pins[2]); else if (config->pins[0]) printk(", usb0 %d wires%s", config->pins[0], @@ -561,12 +444,10 @@ omap_otg_init(struct omap_usb_config *config) printk(", Mini-AB on usb%d", config->otg - 1); printk("\n"); - if (cpu_class_is_omap1()) { - /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; - } + /* leave USB clocks/controllers off until needed */ + ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; + ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; + ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; syscon = OTG_SYSCON_1_REG; syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; @@ -704,7 +585,7 @@ omap_usb_init(void) } platform_data = *config; - if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) + if (cpu_is_omap730() || cpu_is_omap16xx()) omap_otg_init(&platform_data); else if (cpu_is_omap15xx()) omap_1510_usb_init(&platform_data); diff --git a/trunk/arch/arm/plat-s3c24xx/sleep.S b/trunk/arch/arm/plat-s3c24xx/sleep.S index 7b7ae790b00d..435349dc3243 100644 --- a/trunk/arch/arm/plat-s3c24xx/sleep.S +++ b/trunk/arch/arm/plat-s3c24xx/sleep.S @@ -1,4 +1,4 @@ -/* linux/arch/arm/plat-s3c24xx/sleep.S +/* linux/arch/arm/mach-s3c2410/sleep.S * * Copyright (c) 2004 Simtec Electronics * Ben Dooks diff --git a/trunk/arch/avr32/Makefile b/trunk/arch/avr32/Makefile index dc6bc01f232c..6115fc1f0cfa 100644 --- a/trunk/arch/avr32/Makefile +++ b/trunk/arch/avr32/Makefile @@ -16,7 +16,7 @@ AFLAGS += -mrelax -mno-pic CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax -cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000 +cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000 CFLAGS += $(cpuflags-y) AFLAGS += $(cpuflags-y) diff --git a/trunk/arch/avr32/kernel/process.c b/trunk/arch/avr32/kernel/process.c index 13f988402613..4e4181ed1c6d 100644 --- a/trunk/arch/avr32/kernel/process.c +++ b/trunk/arch/avr32/kernel/process.c @@ -330,13 +330,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs *childregs; - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; + childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1; *childregs = *regs; if (user_mode(regs)) childregs->sp = usp; else - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; + childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE; childregs->r12 = 0; /* Set return value for child */ @@ -403,7 +403,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)task_stack_page(p); + stack_page = (unsigned long)p->thread_info; BUG_ON(!stack_page); /* diff --git a/trunk/arch/avr32/kernel/ptrace.c b/trunk/arch/avr32/kernel/ptrace.c index 3c36c2d16148..8ac74dddbbde 100644 --- a/trunk/arch/avr32/kernel/ptrace.c +++ b/trunk/arch/avr32/kernel/ptrace.c @@ -24,7 +24,7 @@ static struct pt_regs *get_user_regs(struct task_struct *tsk) { - return (struct pt_regs *)((unsigned long)task_stack_page(tsk) + + return (struct pt_regs *)((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)); } diff --git a/trunk/arch/avr32/kernel/syscall_table.S b/trunk/arch/avr32/kernel/syscall_table.S index 07f6a6fa340d..7c279586fbba 100644 --- a/trunk/arch/avr32/kernel/syscall_table.S +++ b/trunk/arch/avr32/kernel/syscall_table.S @@ -291,5 +291,4 @@ sys_call_table: .long sys_shmget /* 275 */ .long sys_shmdt .long sys_shmctl - .long sys_utimensat .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/trunk/arch/avr32/kernel/traps.c b/trunk/arch/avr32/kernel/traps.c index 86d107511dd4..4de9edf96ed2 100644 --- a/trunk/arch/avr32/kernel/traps.c +++ b/trunk/arch/avr32/kernel/traps.c @@ -123,7 +123,7 @@ asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs) /* This way of handling undefined instructions is stolen from ARM */ static LIST_HEAD(undef_hook); -static DEFINE_SPINLOCK(undef_lock); +static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; void register_undef_hook(struct undef_hook *hook) { diff --git a/trunk/arch/avr32/kernel/vmlinux.lds.c b/trunk/arch/avr32/kernel/vmlinux.lds.c index e7f72c995a32..7ad20cfb48a8 100644 --- a/trunk/arch/avr32/kernel/vmlinux.lds.c +++ b/trunk/arch/avr32/kernel/vmlinux.lds.c @@ -35,7 +35,7 @@ SECTIONS _einittext = .; . = ALIGN(4); __tagtable_begin = .; - *(.taglist.init) + *(.taglist) __tagtable_end = .; *(.init.data) . = ALIGN(16); diff --git a/trunk/arch/avr32/mach-at32ap/clock.c b/trunk/arch/avr32/mach-at32ap/clock.c index 0f8c89c9f832..00c435452d7e 100644 --- a/trunk/arch/avr32/mach-at32ap/clock.c +++ b/trunk/arch/avr32/mach-at32ap/clock.c @@ -18,7 +18,7 @@ #include "clock.h" -static DEFINE_SPINLOCK(clk_lock); +static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED; struct clk *clk_get(struct device *dev, const char *id) { diff --git a/trunk/arch/avr32/mm/dma-coherent.c b/trunk/arch/avr32/mm/dma-coherent.c index 099212d4567c..b68d669f823d 100644 --- a/trunk/arch/avr32/mm/dma-coherent.c +++ b/trunk/arch/avr32/mm/dma-coherent.c @@ -112,21 +112,16 @@ void dma_free_coherent(struct device *dev, size_t size, } EXPORT_SYMBOL(dma_free_coherent); +#if 0 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) { struct page *page; - dma_addr_t phys; page = __dma_alloc(dev, size, handle, gfp); - if (!page) - return NULL; - - phys = page_to_phys(page); - *handle = phys; /* Now, map the page into P3 with write-combining turned on */ - return __ioremap(phys, size, _PAGE_BUFFER); + return __ioremap(page_to_phys(page), size, _PAGE_BUFFER); } EXPORT_SYMBOL(dma_alloc_writecombine); @@ -137,7 +132,8 @@ void dma_free_writecombine(struct device *dev, size_t size, iounmap(cpu_addr); - page = phys_to_page(handle); + page = bus_to_page(handle); __dma_free(dev, size, page, handle); } EXPORT_SYMBOL(dma_free_writecombine); +#endif diff --git a/trunk/arch/blackfin/kernel/asm-offsets.c b/trunk/arch/blackfin/kernel/asm-offsets.c index e455f4504509..41d9a9f89700 100644 --- a/trunk/arch/blackfin/kernel/asm-offsets.c +++ b/trunk/arch/blackfin/kernel/asm-offsets.c @@ -46,7 +46,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); diff --git a/trunk/arch/blackfin/kernel/ptrace.c b/trunk/arch/blackfin/kernel/ptrace.c index e718bb4a1ef0..d7c8e514cb92 100644 --- a/trunk/arch/blackfin/kernel/ptrace.c +++ b/trunk/arch/blackfin/kernel/ptrace.c @@ -73,7 +73,7 @@ static inline struct pt_regs *get_user_regs(struct task_struct *task) { return (struct pt_regs *) - ((unsigned long)task_stack_page(task) + + ((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); } @@ -99,7 +99,7 @@ static inline long get_reg(struct task_struct *task, int regno) unsigned char *reg_ptr; struct pt_regs *regs = - (struct pt_regs *)((unsigned long)task_stack_page(task) + + (struct pt_regs *)((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); reg_ptr = (char *)regs; @@ -125,7 +125,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data) char * reg_ptr; struct pt_regs *regs = - (struct pt_regs *)((unsigned long)task_stack_page(task) + + (struct pt_regs *)((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); reg_ptr = (char *)regs; diff --git a/trunk/arch/cris/arch-v32/drivers/Kconfig b/trunk/arch/cris/arch-v32/drivers/Kconfig index 1d859c16931e..f64624fc4504 100644 --- a/trunk/arch/cris/arch-v32/drivers/Kconfig +++ b/trunk/arch/cris/arch-v32/drivers/Kconfig @@ -603,7 +603,7 @@ config ETRAX_CARDBUS select HOTPLUG select PCCARD_NONSTATIC help - Enabled the ETRAX Cardbus driver. + Enabled the ETRAX Carbus driver. config PCI bool diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index 114738a45582..eed694312a79 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -45,15 +45,15 @@ config TIME_LOW_RES bool default y -config QUICKLIST +config ARCH_HAS_ILOG2_U32 bool default y -config ARCH_HAS_ILOG2_U32 +config ARCH_HAS_ILOG2_U64 bool default y -config ARCH_HAS_ILOG2_U64 +config ARCH_USES_SLAB_PAGE_STRUCT bool default y diff --git a/trunk/arch/frv/kernel/entry.S b/trunk/arch/frv/kernel/entry.S index 43dc08ec7511..940ac306e9a0 100644 --- a/trunk/arch/frv/kernel/entry.S +++ b/trunk/arch/frv/kernel/entry.S @@ -1482,16 +1482,6 @@ sys_call_table: .long sys_faccessat .long sys_pselect6 .long sys_ppoll - .long sys_unshare /* 310 */ - .long sys_set_robust_list - .long sys_get_robust_list - .long sys_splice - .long sys_sync_file_range - .long sys_tee /* 315 */ - .long sys_vmsplice - .long sys_move_pages - .long sys_getcpu - .long sys_epoll_pwait syscall_table_size = (. - sys_call_table) diff --git a/trunk/arch/frv/kernel/gdb-stub.c b/trunk/arch/frv/kernel/gdb-stub.c index 1e7a101cbf4c..9550f37fb62c 100644 --- a/trunk/arch/frv/kernel/gdb-stub.c +++ b/trunk/arch/frv/kernel/gdb-stub.c @@ -1195,7 +1195,7 @@ static void gdbstub_check_breakpoint(void) /* * */ -static void __maybe_unused gdbstub_show_regs(void) +static void __attribute__((unused)) gdbstub_show_regs(void) { unsigned long *reg; int loop; @@ -1223,7 +1223,7 @@ static void __maybe_unused gdbstub_show_regs(void) /* * dump debugging regs */ -static void __maybe_unused gdbstub_dump_debugregs(void) +static void __attribute__((unused)) gdbstub_dump_debugregs(void) { gdbstub_printk("DCR %08lx ", __debug_status.dcr); gdbstub_printk("BRR %08lx\n", __debug_status.brr); @@ -2079,25 +2079,25 @@ void gdbstub_exit(int status) * GDB wants to call malloc() and free() to allocate memory for calling kernel * functions directly from its command line */ -static void *malloc(size_t size) __maybe_unused; +static void *malloc(size_t size) __attribute__((unused)); static void *malloc(size_t size) { return kmalloc(size, GFP_ATOMIC); } -static void free(void *p) __maybe_unused; +static void free(void *p) __attribute__((unused)); static void free(void *p) { kfree(p); } -static uint32_t ___get_HSR0(void) __maybe_unused; +static uint32_t ___get_HSR0(void) __attribute__((unused)); static uint32_t ___get_HSR0(void) { return __get_HSR(0); } -static uint32_t ___set_HSR0(uint32_t x) __maybe_unused; +static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused)); static uint32_t ___set_HSR0(uint32_t x) { __set_HSR(0, x); diff --git a/trunk/arch/frv/kernel/process.c b/trunk/arch/frv/kernel/process.c index 9583a338e9d6..515a5cea5469 100644 --- a/trunk/arch/frv/kernel/process.c +++ b/trunk/arch/frv/kernel/process.c @@ -25,14 +25,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -90,8 +88,6 @@ void cpu_idle(void) while (!need_resched()) { irq_stat[cpu].idle_timestamp = jiffies; - check_pgt_cache(); - if (!frv_dma_inprogress && idle) idle(); } diff --git a/trunk/arch/frv/kernel/setup.c b/trunk/arch/frv/kernel/setup.c index aa3c795d5354..8ea3ca2aba62 100644 --- a/trunk/arch/frv/kernel/setup.c +++ b/trunk/arch/frv/kernel/setup.c @@ -191,7 +191,7 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = { static const struct clock_cmode __pminitdata *clock_cmodes; static int __pminitdata clock_doubled; -static struct uart_port __pminitdata __frv_uart0 = { +static struct uart_port __initdata __frv_uart0 = { .uartclk = 0, .membase = (char *) UART0_BASE, .irq = IRQ_CPU_UART0, @@ -200,7 +200,7 @@ static struct uart_port __pminitdata __frv_uart0 = { .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, }; -static struct uart_port __pminitdata __frv_uart1 = { +static struct uart_port __initdata __frv_uart1 = { .uartclk = 0, .membase = (char *) UART1_BASE, .irq = IRQ_CPU_UART1, diff --git a/trunk/arch/frv/mm/elf-fdpic.c b/trunk/arch/frv/mm/elf-fdpic.c index 385fd30b142f..cac2c01a3a56 100644 --- a/trunk/arch/frv/mm/elf-fdpic.c +++ b/trunk/arch/frv/mm/elf-fdpic.c @@ -13,7 +13,6 @@ #include #include #include -#include /*****************************************************************************/ /* diff --git a/trunk/arch/frv/mm/pgalloc.c b/trunk/arch/frv/mm/pgalloc.c index 7787c3cc52c6..598a26ab8ad8 100644 --- a/trunk/arch/frv/mm/pgalloc.c +++ b/trunk/arch/frv/mm/pgalloc.c @@ -13,12 +13,12 @@ #include #include #include -#include #include #include #include pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE))); +struct kmem_cache *pgd_cache; pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { @@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long) pprev); } -void pgd_ctor(void *pgd) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -120,7 +120,7 @@ void pgd_ctor(void *pgd) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ @@ -133,7 +133,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *pgd; - pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); + pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); if (!pgd) return pgd; @@ -143,15 +143,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm) void pgd_free(pgd_t *pgd) { /* in the non-PAE case, clear_page_tables() clears user pgd entries */ - quicklist_free(0, pgd_dtor, pgd); + kmem_cache_free(pgd_cache, pgd); } void __init pgtable_cache_init(void) { + pgd_cache = kmem_cache_create("pgd", + PTRS_PER_PGD * sizeof(pgd_t), + PTRS_PER_PGD * sizeof(pgd_t), + SLAB_PANIC, + pgd_ctor, + pgd_dtor); } - -void check_pgt_cache(void) -{ - quicklist_trim(0, pgd_dtor, 25, 16); -} - diff --git a/trunk/arch/h8300/Kconfig.debug b/trunk/arch/h8300/Kconfig.debug index 554efe604a08..e0e9bcb015a9 100644 --- a/trunk/arch/h8300/Kconfig.debug +++ b/trunk/arch/h8300/Kconfig.debug @@ -21,12 +21,12 @@ config GDB_MAGICPRINT bool "Message Output for GDB MagicPrint service" depends on (H8300H_SIM || H8S_SIM) help - kernel messages output using MagicPrint service from GDB + kernel messages output useing MagicPrint service from GDB config SYSCALL_PRINT bool "SystemCall trace print" help - output history of systemcall + outout history of systemcall config GDB_DEBUG bool "Use gdb stub" diff --git a/trunk/arch/h8300/kernel/asm-offsets.c b/trunk/arch/h8300/kernel/asm-offsets.c index fc30b4fd0914..b78b82ad28a3 100644 --- a/trunk/arch/h8300/kernel/asm-offsets.c +++ b/trunk/arch/h8300/kernel/asm-offsets.c @@ -30,7 +30,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); diff --git a/trunk/arch/h8300/kernel/syscalls.S b/trunk/arch/h8300/kernel/syscalls.S index 54e21c3f2057..dab98fd99e63 100644 --- a/trunk/arch/h8300/kernel/syscalls.S +++ b/trunk/arch/h8300/kernel/syscalls.S @@ -31,7 +31,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_mknod) .long SYMBOL_NAME(sys_chmod) /* 15 */ .long SYMBOL_NAME(sys_chown16) - .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ .long SYMBOL_NAME(sys_stat) .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ @@ -45,11 +45,11 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_fstat) .long SYMBOL_NAME(sys_pause) .long SYMBOL_NAME(sys_utime) /* 30 */ - .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ - .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ .long SYMBOL_NAME(sys_access) .long SYMBOL_NAME(sys_nice) - .long SYMBOL_NAME(sys_ni_syscall) /* 35 old ftime syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ .long SYMBOL_NAME(sys_sync) .long SYMBOL_NAME(sys_kill) .long SYMBOL_NAME(sys_rename) @@ -58,7 +58,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_dup) .long SYMBOL_NAME(sys_pipe) .long SYMBOL_NAME(sys_times) - .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ .long SYMBOL_NAME(sys_brk) /* 45 */ .long SYMBOL_NAME(sys_setgid16) .long SYMBOL_NAME(sys_getgid16) @@ -66,13 +66,13 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_geteuid16) .long SYMBOL_NAME(sys_getegid16) /* 50 */ .long SYMBOL_NAME(sys_acct) - .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ - .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ + .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ + .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ - .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ .long SYMBOL_NAME(sys_setpgid) - .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_umask) /* 60 */ .long SYMBOL_NAME(sys_chroot) @@ -112,7 +112,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_fchown16) /* 95 */ .long SYMBOL_NAME(sys_getpriority) .long SYMBOL_NAME(sys_setpriority) - .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ + .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ .long SYMBOL_NAME(sys_statfs) .long SYMBOL_NAME(sys_fstatfs) /* 100 */ .long SYMBOL_NAME(sys_ni_syscall) /* ioperm for i386 */ @@ -202,8 +202,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_capset) /* 185 */ .long SYMBOL_NAME(sys_sigaltstack) .long SYMBOL_NAME(sys_sendfile) - .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ - .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_getrlimit) .long SYMBOL_NAME(sys_mmap2) @@ -236,10 +236,10 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) - .long SYMBOL_NAME(sys_ni_syscall) /* reserved TUX */ - .long SYMBOL_NAME(sys_ni_syscall) /* reserved Security */ + .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ + .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_gettid) - .long SYMBOL_NAME(sys_readahead) /* 225 */ + .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ /* sys_readahead */ .long SYMBOL_NAME(sys_setxattr) .long SYMBOL_NAME(sys_lsetxattr) .long SYMBOL_NAME(sys_fsetxattr) @@ -257,8 +257,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_futex) /* 240 */ .long SYMBOL_NAME(sys_sched_setaffinity) .long SYMBOL_NAME(sys_sched_getaffinity) - .long SYMBOL_NAME(sys_ni_syscall) - .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ + .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */ .long SYMBOL_NAME(sys_io_setup) /* 245 */ .long SYMBOL_NAME(sys_io_destroy) .long SYMBOL_NAME(sys_io_getevents) @@ -288,8 +288,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_utimes) .long SYMBOL_NAME(sys_fadvise64_64) .long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */ - .long SYMBOL_NAME(sys_ni_syscall) - .long SYMBOL_NAME(sys_get_mempolicy) /* 275 */ + .long SYMBOL_NAME(sys_mbind) + .long SYMBOL_NAME(sys_get_mempolicy) .long SYMBOL_NAME(sys_set_mempolicy) .long SYMBOL_NAME(sys_mq_open) .long SYMBOL_NAME(sys_mq_unlink) @@ -297,42 +297,16 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */ .long SYMBOL_NAME(sys_mq_notify) .long SYMBOL_NAME(sys_mq_getsetattr) + .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */ .long SYMBOL_NAME(sys_waitid) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_kexec_load */ - .long SYMBOL_NAME(sys_add_key) /* 285 */ + .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */ + .long SYMBOL_NAME(sys_add_key) .long SYMBOL_NAME(sys_request_key) .long SYMBOL_NAME(sys_keyctl) - .long SYMBOL_NAME(sys_ioprio_set) - .long SYMBOL_NAME(sys_ioprio_get) /* 290 */ - .long SYMBOL_NAME(sys_inotify_init) - .long SYMBOL_NAME(sys_inotify_add_watch) - .long SYMBOL_NAME(sys_inotify_rm_watch) - .long SYMBOL_NAME(sys_migrate_pages) - .long SYMBOL_NAME(sys_openat) /* 295 */ - .long SYMBOL_NAME(sys_mkdirat) - .long SYMBOL_NAME(sys_mknodat) - .long SYMBOL_NAME(sys_fchownat) - .long SYMBOL_NAME(sys_futimesat) - .long SYMBOL_NAME(sys_fstatat64) /* 300 */ - .long SYMBOL_NAME(sys_unlinkat) - .long SYMBOL_NAME(sys_renameat) - .long SYMBOL_NAME(sys_linkat) - .long SYMBOL_NAME(sys_symlinkat) - .long SYMBOL_NAME(sys_readlinkat) /* 305 */ - .long SYMBOL_NAME(sys_fchmodat) - .long SYMBOL_NAME(sys_faccessat) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_pselect6 */ - .long SYMBOL_NAME(sys_ni_syscall) /* sys_ppoll */ - .long SYMBOL_NAME(sys_unshare) /* 310 */ - .long SYMBOL_NAME(sys_set_robust_list) - .long SYMBOL_NAME(sys_get_robust_list) - .long SYMBOL_NAME(sys_splice) - .long SYMBOL_NAME(sys_sync_file_range) - .long SYMBOL_NAME(sys_tee) /* 315 */ - .long SYMBOL_NAME(sys_vmsplice) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_move_pages */ - .long SYMBOL_NAME(sys_getcpu) - .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_pwait */ + + .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 + .long SYMBOL_NAME(sys_ni_syscall) + .endr .macro call_sp addr mov.l #SYMBOL_NAME(\addr),er6 diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index 30944ee2e61a..64ad10f984a1 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -858,9 +858,9 @@ config RELOCATABLE bool "Build a relocatable kernel(EXPERIMENTAL)" depends on EXPERIMENTAL help - This builds a kernel image that retains relocation information + This build a kernel image that retains relocation information so it can be loaded someplace besides the default 1MB. - The relocations tend to make the kernel binary about 10% larger, + The relocations tend to the kernel binary about 10% larger, but are discarded at runtime. One use is for the kexec on panic case where the recovery kernel diff --git a/trunk/arch/i386/Kconfig.cpu b/trunk/arch/i386/Kconfig.cpu index d7f6fb0b30f2..dce6124cb842 100644 --- a/trunk/arch/i386/Kconfig.cpu +++ b/trunk/arch/i386/Kconfig.cpu @@ -108,7 +108,7 @@ config MCORE2 bool "Core 2/newer Xeon" help Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) - CPUs. You can distinguish newer from older Xeons by the CPU family + CPUs. You can distingush newer from older Xeons by the CPU family in /proc/cpuinfo. Newer ones have 6. config MPENTIUM4 @@ -172,7 +172,7 @@ config MWINCHIP3D help Select this for an IDT Winchip-2A or 3. Linux and GCC treat this chip as a 586TSC with some extended instructions - and alignment requirements. Also enable out of order memory + and alignment reqirements. Also enable out of order memory stores for this CPU, which can increase performance of some operations. diff --git a/trunk/arch/i386/boot/video.S b/trunk/arch/i386/boot/video.S index 8143c9516cb4..5e2280cf4456 100644 --- a/trunk/arch/i386/boot/video.S +++ b/trunk/arch/i386/boot/video.S @@ -496,9 +496,11 @@ mode_set: cmpb $VIDEO_FIRST_V7>>8, %ah jz setv7 +#ifdef CONFIG_FB cmpb $VIDEO_FIRST_VESA>>8, %ah jnc check_vesa - +#endif + orb %ah, %ah jz setmenu diff --git a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c index e5be819492ef..80b4c5d421b1 100644 --- a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -733,11 +733,9 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cache_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cache_remove_dev(sys_dev); break; } diff --git a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c index 7ba7c3abd3a4..065005c3f168 100644 --- a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -1,5 +1,5 @@ /* - * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c + * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c * * Thermal throttle event support code (such as syslog messaging and rate * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c). @@ -137,12 +137,10 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, mutex_lock(&therm_cpu_lock); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: err = thermal_throttle_add_dev(sys_dev); WARN_ON(err); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: thermal_throttle_remove_dev(sys_dev); break; } diff --git a/trunk/arch/i386/kernel/cpu/transmeta.c b/trunk/arch/i386/kernel/cpu/transmeta.c index 200fb3f9ebfb..6471a5a13202 100644 --- a/trunk/arch/i386/kernel/cpu/transmeta.c +++ b/trunk/arch/i386/kernel/cpu/transmeta.c @@ -77,10 +77,8 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); /* If we can run i686 user-space code, call us an i686 */ -#define USER686 ((1 << X86_FEATURE_TSC)|\ - (1 << X86_FEATURE_CX8)|\ - (1 << X86_FEATURE_CMOV)) - if (c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686) +#define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV) + if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 ) c->x86 = 6; #ifdef CONFIG_SYSCTL diff --git a/trunk/arch/i386/kernel/cpuid.c b/trunk/arch/i386/kernel/cpuid.c index 5c2faa10e9fa..eeae0d992337 100644 --- a/trunk/arch/i386/kernel/cpuid.c +++ b/trunk/arch/i386/kernel/cpuid.c @@ -169,11 +169,9 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpuid_device_create(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); break; } diff --git a/trunk/arch/i386/kernel/head.S b/trunk/arch/i386/kernel/head.S index f74dfc419b56..9b10af65faaa 100644 --- a/trunk/arch/i386/kernel/head.S +++ b/trunk/arch/i386/kernel/head.S @@ -71,6 +71,12 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_ .section .text.head,"ax",@progbits ENTRY(startup_32) +#ifdef CONFIG_PARAVIRT + movl %cs, %eax + testl $0x3, %eax + jnz startup_paravirt +#endif + /* * Set segments to known values. */ @@ -495,6 +501,38 @@ ignore_int: iret .section .text +#ifdef CONFIG_PARAVIRT +startup_paravirt: + cld + movl $(init_thread_union+THREAD_SIZE),%esp + + /* We take pains to preserve all the regs. */ + pushl %edx + pushl %ecx + pushl %eax + + pushl $__start_paravirtprobe +1: + movl 0(%esp), %eax + cmpl $__stop_paravirtprobe, %eax + je unhandled_paravirt + pushl (%eax) + movl 8(%esp), %eax + call *(%esp) + popl %eax + + movl 4(%esp), %eax + movl 8(%esp), %ecx + movl 12(%esp), %edx + + addl $4, (%esp) + jmp 1b + +unhandled_paravirt: + /* Nothing wanted us: we're screwed. */ + ud2 +#endif + /* * Real beginning of normal "text" segment */ diff --git a/trunk/arch/i386/kernel/microcode.c b/trunk/arch/i386/kernel/microcode.c index 83f825f2e2d7..cbe7ec8dbb9f 100644 --- a/trunk/arch/i386/kernel/microcode.c +++ b/trunk/arch/i386/kernel/microcode.c @@ -567,7 +567,7 @@ static int cpu_request_microcode(int cpu) return error; } -static int apply_microcode_check_cpu(int cpu) +static int apply_microcode_on_cpu(int cpu) { struct cpuinfo_x86 *c = cpu_data + cpu; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -575,9 +575,8 @@ static int apply_microcode_check_cpu(int cpu) unsigned int val[2]; int err = 0; - /* Check if the microcode is available */ if (!uci->mc) - return 0; + return -EINVAL; old = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(cpu)); @@ -615,7 +614,7 @@ static int apply_microcode_check_cpu(int cpu) return err; } -static void microcode_init_cpu(int cpu, int resume) +static void microcode_init_cpu(int cpu) { cpumask_t old; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -625,7 +624,8 @@ static void microcode_init_cpu(int cpu, int resume) set_cpus_allowed(current, cpumask_of_cpu(cpu)); mutex_lock(µcode_mutex); collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) + if (uci->valid && system_state == SYSTEM_RUNNING && + !suspend_cpu_hotplug) cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); set_cpus_allowed(current, old); @@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = { .name = "microcode", }; -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +static int mc_sysdev_add(struct sys_device *sys_dev) { int err, cpu = sys_dev->id; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -711,31 +711,39 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) return 0; pr_debug("Microcode:CPU %d added\n", cpu); - memset(uci, 0, sizeof(*uci)); + /* If suspend_cpu_hotplug is set, the system is resuming and we should + * use the data from before the suspend. + */ + if (suspend_cpu_hotplug) { + err = apply_microcode_on_cpu(cpu); + if (err) + microcode_fini_cpu(cpu); + } + if (!uci->valid) + memset(uci, 0, sizeof(*uci)); err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); if (err) return err; - microcode_init_cpu(cpu, resume); + if (!uci->valid) + microcode_init_cpu(cpu); return 0; } -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - static int mc_sysdev_remove(struct sys_device *sys_dev) { int cpu = sys_dev->id; if (!cpu_online(cpu)) return 0; - pr_debug("Microcode:CPU %d removed\n", cpu); - microcode_fini_cpu(cpu); + /* If suspend_cpu_hotplug is set, the system is suspending and we should + * keep the microcode in memory for the resume. + */ + if (!suspend_cpu_hotplug) + microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; } @@ -766,34 +774,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) sys_dev = get_cpu_sysdev(cpu); switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; case CPU_ONLINE: case CPU_DOWN_FAILED: mc_sysdev_add(sys_dev); break; - case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } - case CPU_DOWN_FAILED_FROZEN: - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "Microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; case CPU_DOWN_PREPARE: mc_sysdev_remove(sys_dev); break; - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - break; } return NOTIFY_OK; } diff --git a/trunk/arch/i386/kernel/msr.c b/trunk/arch/i386/kernel/msr.c index 0c1069b8d638..8cd0a91ce107 100644 --- a/trunk/arch/i386/kernel/msr.c +++ b/trunk/arch/i386/kernel/msr.c @@ -153,11 +153,9 @@ static int msr_class_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: msr_device_create(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); break; } diff --git a/trunk/arch/i386/kernel/paravirt.c b/trunk/arch/i386/kernel/paravirt.c index faab09abca5e..5c10f376bce1 100644 --- a/trunk/arch/i386/kernel/paravirt.c +++ b/trunk/arch/i386/kernel/paravirt.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/trunk/arch/i386/kernel/syscall_table.S b/trunk/arch/i386/kernel/syscall_table.S index bf6adce52267..0772678ceecf 100644 --- a/trunk/arch/i386/kernel/syscall_table.S +++ b/trunk/arch/i386/kernel/syscall_table.S @@ -320,6 +320,3 @@ ENTRY(sys_call_table) .long sys_getcpu .long sys_epoll_pwait .long sys_utimensat /* 320 */ - .long sys_signalfd - .long sys_timerfd - .long sys_eventfd diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index c05e7e861b29..4bec0cbf407a 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -305,7 +305,7 @@ void show_registers(struct pt_regs *regs) regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss); printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", TASK_COMM_LEN, current->comm, current->pid, - current_thread_info(), current, task_thread_info(current)); + current_thread_info(), current, current->thread_info); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. diff --git a/trunk/arch/i386/kernel/vmlinux.lds.S b/trunk/arch/i386/kernel/vmlinux.lds.S index 80bec6640230..23e8614edeee 100644 --- a/trunk/arch/i386/kernel/vmlinux.lds.S +++ b/trunk/arch/i386/kernel/vmlinux.lds.S @@ -78,6 +78,12 @@ SECTIONS CONSTRUCTORS } :data + .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) { + __start_paravirtprobe = .; + *(.paravirtprobe) + __stop_paravirtprobe = .; + } + . = ALIGN(4096); .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { __nosave_begin = .; diff --git a/trunk/arch/i386/mach-generic/probe.c b/trunk/arch/i386/mach-generic/probe.c index 74f3da634423..a7b3999bb37a 100644 --- a/trunk/arch/i386/mach-generic/probe.c +++ b/trunk/arch/i386/mach-generic/probe.c @@ -119,7 +119,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } +#ifdef CONFIG_SMP int hard_smp_processor_id(void) { return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); } +#endif diff --git a/trunk/arch/i386/mach-voyager/voyager_basic.c b/trunk/arch/i386/mach-voyager/voyager_basic.c index 9b77b39b71a6..8fe7e4593d5f 100644 --- a/trunk/arch/i386/mach-voyager/voyager_basic.c +++ b/trunk/arch/i386/mach-voyager/voyager_basic.c @@ -292,8 +292,8 @@ machine_emergency_restart(void) void mca_nmi_hook(void) { - __u8 dumpval __maybe_unused = inb(0xf823); - __u8 swnmi __maybe_unused = inb(0xf813); + __u8 dumpval __attribute__((unused)) = inb(0xf823); + __u8 swnmi __attribute__((unused)) = inb(0xf813); /* FIXME: assume dump switch pressed */ /* check to see if the dump switch was pressed */ diff --git a/trunk/arch/i386/pci/init.c b/trunk/arch/i386/pci/init.c index 3de9f9ba2da6..1cf11af96de2 100644 --- a/trunk/arch/i386/pci/init.c +++ b/trunk/arch/i386/pci/init.c @@ -6,7 +6,7 @@ in the right sequence from here. */ static __init int pci_access_init(void) { - int type __maybe_unused = 0; + int type __attribute__((unused)) = 0; #ifdef CONFIG_PCI_DIRECT type = pci_direct_probe(); diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 6e41471449c0..e23af4b6ae8c 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -468,7 +468,7 @@ config KEXEC help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot - but it is independent of the system firmware. And like a reboot + but it is indepedent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. The name comes from the similiarity to the exec system call. diff --git a/trunk/arch/ia64/ia32/ia32_entry.S b/trunk/arch/ia64/ia32/ia32_entry.S index 99b665e2b1d5..687e5fdc9683 100644 --- a/trunk/arch/ia64/ia32/ia32_entry.S +++ b/trunk/arch/ia64/ia32/ia32_entry.S @@ -52,6 +52,43 @@ ENTRY(ia32_clone) br.ret.sptk.many rp END(ia32_clone) +ENTRY(sys32_rt_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs + mov loc0=rp + mov out0=in0 // mask + mov out1=in1 // sigsetsize + mov out2=sp // out2 = &sigscratch + .fframe 16 + adds sp=-16,sp // allocate dummy "sigscratch" + ;; + .body + br.call.sptk.many rp=ia32_rt_sigsuspend +1: .restore sp + adds sp=16,sp + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys32_rt_sigsuspend) + +ENTRY(sys32_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs + mov loc0=rp + mov out0=in2 // mask (first two args are ignored) + ;; + mov out1=sp // out1 = &sigscratch + .fframe 16 + adds sp=-16,sp // allocate dummy "sigscratch" + .body + br.call.sptk.many rp=ia32_sigsuspend +1: .restore sp + adds sp=16,sp + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys32_sigsuspend) + GLOBAL_ENTRY(ia32_ret_from_clone) PT_REGS_UNWIND_INFO(0) { /* @@ -352,7 +389,7 @@ ia32_syscall_table: data8 sys_rt_sigpending data8 compat_sys_rt_sigtimedwait data8 sys32_rt_sigqueueinfo - data8 compat_sys_rt_sigsuspend + data8 sys32_rt_sigsuspend data8 sys32_pread /* 180 */ data8 sys32_pwrite data8 sys_chown /* 16-bit version */ diff --git a/trunk/arch/ia64/ia32/ia32_signal.c b/trunk/arch/ia64/ia32/ia32_signal.c index 85e82f32e480..10510e585204 100644 --- a/trunk/arch/ia64/ia32/ia32_signal.c +++ b/trunk/arch/ia64/ia32/ia32_signal.c @@ -451,20 +451,59 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); } -asmlinkage long -sys32_sigsuspend (int history0, int history1, old_sigset_t mask) +long +__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) { - mask &= _BLOCKABLE; + extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); + sigset_t oldset, set; + + scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */ + memset(&set, 0, sizeof(set)); + + memcpy(&set.sig, &sset->sig, sigsetsize); + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); + { + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(); + } spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; + /* + * The return below usually returns to the signal handler. We need to pre-set the + * correct error code here to ensure that the right values get saved in sigcontext + * by ia64_do_signal. + */ + scr->pt.r8 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (ia64_do_signal(&oldset, scr, 1)) + return -EINTR; + } +} + +asmlinkage long +ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr) +{ + compat_sigset_t set; + + if (sigsetsize > sizeof(compat_sigset_t)) + return -EINVAL; + + if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) + return -EFAULT; + + return __ia32_rt_sigsuspend(&set, sigsetsize, scr); +} + +asmlinkage long +ia32_sigsuspend (unsigned int mask, struct sigscratch *scr) +{ + return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr); } asmlinkage long @@ -771,11 +810,7 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) } /* Legacy stack switching not supported */ - esp -= frame_size; - /* Align the stack pointer according to the i386 ABI, - * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - esp = ((esp + 4) & -16ul) - 4; - return (void __user *) esp; + return (void __user *)((esp - frame_size) & -8ul); } static int diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index b50bf208678e..55fd2d5471e1 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1199,6 +1199,32 @@ ENTRY(notify_resume_user) br.ret.sptk.many rp END(notify_resume_user) +GLOBAL_ENTRY(sys_rt_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! + mov r9=ar.unat + mov loc0=rp // save return address + mov out0=in0 // mask + mov out1=in1 // sigsetsize + adds out2=8,sp // out2=&sigscratch->ar_pfs + ;; + .fframe 16 + .spillsp ar.unat, 16 + st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch + .body + br.call.sptk.many rp=ia64_rt_sigsuspend +.ret17: .restore sp + adds sp=16,sp // pop scratch stack space + ;; + ld8 r9=[sp] // load new unat from sw->caller_unat + mov rp=loc0 + ;; + mov ar.unat=r9 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys_rt_sigsuspend) + ENTRY(sys_rt_sigreturn) PT_REGS_UNWIND_INFO(0) /* @@ -1572,8 +1598,8 @@ sys_call_table: data8 sys_readlinkat data8 sys_fchmodat data8 sys_faccessat - data8 sys_pselect6 - data8 sys_ppoll + data8 sys_ni_syscall // reserved for pselect + data8 sys_ni_syscall // 1295 reserved for ppoll data8 sys_unshare data8 sys_splice data8 sys_set_robust_list diff --git a/trunk/arch/ia64/kernel/err_inject.c b/trunk/arch/ia64/kernel/err_inject.c index 6a49600cf337..d3e9f33e8bdd 100644 --- a/trunk/arch/ia64/kernel/err_inject.c +++ b/trunk/arch/ia64/kernel/err_inject.c @@ -236,11 +236,9 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: err_inject_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: err_inject_remove_dev(sys_dev); break; } diff --git a/trunk/arch/ia64/kernel/iosapic.c b/trunk/arch/ia64/kernel/iosapic.c index 37f46527d233..93d9ab14ba24 100644 --- a/trunk/arch/ia64/kernel/iosapic.c +++ b/trunk/arch/ia64/kernel/iosapic.c @@ -1012,7 +1012,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, /* * ACPI calls this when it finds an entry for a legacy ISA IRQ override. */ -void __devinit +void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, unsigned long trigger) diff --git a/trunk/arch/ia64/kernel/irq_ia64.c b/trunk/arch/ia64/kernel/irq_ia64.c index bc47049f060f..1c5044a80958 100644 --- a/trunk/arch/ia64/kernel/irq_ia64.c +++ b/trunk/arch/ia64/kernel/irq_ia64.c @@ -38,7 +38,6 @@ #include #include #include -#include #ifdef CONFIG_PERFMON # include @@ -127,10 +126,8 @@ void destroy_irq(unsigned int irq) #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) -# define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH) #else # define IS_RESCHEDULE(vec) (0) -# define IS_LOCAL_TLB_FLUSH(vec) (0) #endif /* * That's where the IVT branches when we get an external @@ -182,11 +179,8 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { - smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; - } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; else { ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); @@ -232,11 +226,8 @@ void ia64_process_pending_intr(void) * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { - smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; - } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; else { struct pt_regs *old_regs = set_irq_regs(NULL); @@ -268,12 +259,12 @@ void ia64_process_pending_intr(void) #ifdef CONFIG_SMP +extern irqreturn_t handle_IPI (int irq, void *dev_id); static irqreturn_t dummy_handler (int irq, void *dev_id) { BUG(); } -extern irqreturn_t handle_IPI (int irq, void *dev_id); static struct irqaction ipi_irqaction = { .handler = handle_IPI, @@ -286,13 +277,6 @@ static struct irqaction resched_irqaction = { .flags = IRQF_DISABLED, .name = "resched" }; - -static struct irqaction tlb_irqaction = { - .handler = dummy_handler, - .flags = IRQF_DISABLED, - .name = "tlb_flush" -}; - #endif void @@ -318,7 +302,6 @@ init_IRQ (void) #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); - register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); #endif #ifdef CONFIG_PERFMON pfm_init_percpu(); diff --git a/trunk/arch/ia64/kernel/mca.c b/trunk/arch/ia64/kernel/mca.c index f8ae709de0b5..1d7cc7e2ce32 100644 --- a/trunk/arch/ia64/kernel/mca.c +++ b/trunk/arch/ia64/kernel/mca.c @@ -1689,7 +1689,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, ti->preempt_count = 1; ti->task = p; ti->cpu = cpu; - p->stack = ti; + p->thread_info = ti; p->state = TASK_UNINTERRUPTIBLE; cpu_set(cpu, p->cpus_allowed); INIT_LIST_HEAD(&p->tasks); diff --git a/trunk/arch/ia64/kernel/palinfo.c b/trunk/arch/ia64/kernel/palinfo.c index 85829e27785c..a71df9ae0397 100644 --- a/trunk/arch/ia64/kernel/palinfo.c +++ b/trunk/arch/ia64/kernel/palinfo.c @@ -975,11 +975,9 @@ static int palinfo_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: create_palinfo_proc_entries(hotcpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: remove_palinfo_proc_entries(hotcpu); break; } diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index d1c3ed9943e5..8bb571a8a738 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -155,7 +155,7 @@ show_regs (struct pt_regs *regs) } void -do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall) +do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { if (fsys_mode(current, &scr->pt)) { /* defer signal-handling etc. until we return to privilege-level 0. */ @@ -170,8 +170,8 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall #endif /* deal with pending signal delivery */ - if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK)) - ia64_do_signal(scr, in_syscall); + if (test_thread_flag(TIF_SIGPENDING)) + ia64_do_signal(oldset, scr, in_syscall); } static int pal_halt = 1; @@ -236,7 +236,6 @@ void cpu_idle_wait(void) { unsigned int cpu, this_cpu = get_cpu(); cpumask_t map; - cpumask_t tmp = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); put_cpu(); @@ -258,7 +257,6 @@ void cpu_idle_wait(void) } cpus_and(map, map, cpu_online_map); } while (!cpus_empty(map)); - set_cpus_allowed(current, tmp); } EXPORT_SYMBOL_GPL(cpu_idle_wait); diff --git a/trunk/arch/ia64/kernel/relocate_kernel.S b/trunk/arch/ia64/kernel/relocate_kernel.S index 903babd22d62..ae473e3f2a0d 100644 --- a/trunk/arch/ia64/kernel/relocate_kernel.S +++ b/trunk/arch/ia64/kernel/relocate_kernel.S @@ -94,7 +94,7 @@ GLOBAL_ENTRY(relocate_new_kernel) 4: srlz.i ;; - // purge TR entry for kernel text and data + //purge TR entry for kernel text and data movl r16=KERNEL_START mov r18=KERNEL_TR_PAGE_SHIFT<<2 ;; @@ -104,6 +104,15 @@ GLOBAL_ENTRY(relocate_new_kernel) srlz.i ;; + // purge TR entry for percpu data + movl r16=PERCPU_ADDR + mov r18=PERCPU_PAGE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.d + ;; + // purge TR entry for pal code mov r16=in3 mov r18=IA64_GRANULE_SHIFT<<2 diff --git a/trunk/arch/ia64/kernel/salinfo.c b/trunk/arch/ia64/kernel/salinfo.c index 89f6b138a62c..a51f1d0bfb70 100644 --- a/trunk/arch/ia64/kernel/salinfo.c +++ b/trunk/arch/ia64/kernel/salinfo.c @@ -582,7 +582,6 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu struct salinfo_data *data; switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: spin_lock_irqsave(&data_saved_lock, flags); for (i = 0, data = salinfo_data; i < ARRAY_SIZE(salinfo_data); @@ -593,7 +592,6 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu spin_unlock_irqrestore(&data_saved_lock, flags); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: spin_lock_irqsave(&data_saved_lock, flags); for (i = 0, data = salinfo_data; i < ARRAY_SIZE(salinfo_data); diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index 9df1efe7487d..6e19da122ae3 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -786,7 +786,7 @@ identify_cpu (struct cpuinfo_ia64 *c) c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); } -void __init +void setup_per_cpu_areas (void) { /* start_kernel() requires this... */ diff --git a/trunk/arch/ia64/kernel/sigframe.h b/trunk/arch/ia64/kernel/sigframe.h index 9fd9a1933b3d..37b986cb86e0 100644 --- a/trunk/arch/ia64/kernel/sigframe.h +++ b/trunk/arch/ia64/kernel/sigframe.h @@ -22,4 +22,4 @@ struct sigframe { struct sigcontext sc; }; -extern void ia64_do_signal (struct sigscratch *, long); +extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index aeec8184e862..0dcd56da6001 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -40,6 +40,47 @@ # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) #endif +long +ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) +{ + sigset_t oldset, set; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (!access_ok(VERIFY_READ, uset, sigsetsize)) + return -EFAULT; + + if (GET_SIGSET(&set, uset)) + return -EFAULT; + + sigdelsetmask(&set, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + { + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(); + } + spin_unlock_irq(¤t->sighand->siglock); + + /* + * The return below usually returns to the signal handler. We need to + * pre-set the correct error code here to ensure that the right values + * get saved in sigcontext by ia64_do_signal. + */ + scr->pt.r8 = EINTR; + scr->pt.r10 = -1; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (ia64_do_signal(&oldset, scr, 1)) + return -EINTR; + } +} + asmlinkage long sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, @@ -436,11 +477,10 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse * Note that `init' is a special process: it doesn't get signals it doesn't want to * handle. Thus you cannot kill init even with a SIGKILL even by mistake. */ -void -ia64_do_signal (struct sigscratch *scr, long in_syscall) +long +ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { struct k_sigaction ka; - sigset_t *oldset; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; @@ -452,11 +492,9 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * doing anything if so. */ if (!user_mode(&scr->pt)) - return; + return 0; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else + if (!oldset) oldset = ¤t->blocked; /* @@ -519,15 +557,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * Whee! Actually deliver the signal. If the delivery failed, we need to * continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &ka, &info, oldset, scr)) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - return; - } + if (handle_signal(signr, &ka, &info, oldset, scr)) + return 1; } /* Did we come from a system call? */ @@ -553,11 +584,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) } } } - - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + return 0; } diff --git a/trunk/arch/ia64/kernel/smp.c b/trunk/arch/ia64/kernel/smp.c index 221de3804560..55ddd809b02d 100644 --- a/trunk/arch/ia64/kernel/smp.c +++ b/trunk/arch/ia64/kernel/smp.c @@ -49,18 +49,6 @@ #include #include -/* - * Note: alignment of 4 entries/cacheline was empirically determined - * to be a good tradeoff between hot cachelines & spreading the array - * across too many cacheline. - */ -static struct local_tlb_flush_counts { - unsigned int count; -} __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS]; - -static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_aligned; - - /* * Structure and data for smp_call_function(). This is designed to minimise static memory * requirements. It also looks cleaner. @@ -260,62 +248,6 @@ smp_send_reschedule (int cpu) platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0); } -/* - * Called with preeemption disabled. - */ -static void -smp_send_local_flush_tlb (int cpu) -{ - platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0); -} - -void -smp_local_flush_tlb(void) -{ - /* - * Use atomic ops. Otherwise, the load/increment/store sequence from - * a "++" operation can have the line stolen between the load & store. - * The overhead of the atomic op in negligible in this case & offers - * significant benefit for the brief periods where lots of cpus - * are simultaneously flushing TLBs. - */ - ia64_fetchadd(1, &local_tlb_flush_counts[smp_processor_id()].count, acq); - local_flush_tlb_all(); -} - -#define FLUSH_DELAY 5 /* Usec backoff to eliminate excessive cacheline bouncing */ - -void -smp_flush_tlb_cpumask(cpumask_t xcpumask) -{ - unsigned int *counts = __ia64_per_cpu_var(shadow_flush_counts); - cpumask_t cpumask = xcpumask; - int mycpu, cpu, flush_mycpu = 0; - - preempt_disable(); - mycpu = smp_processor_id(); - - for_each_cpu_mask(cpu, cpumask) - counts[cpu] = local_tlb_flush_counts[cpu].count; - - mb(); - for_each_cpu_mask(cpu, cpumask) { - if (cpu == mycpu) - flush_mycpu = 1; - else - smp_send_local_flush_tlb(cpu); - } - - if (flush_mycpu) - smp_local_flush_tlb(); - - for_each_cpu_mask(cpu, cpumask) - while(counts[cpu] == local_tlb_flush_counts[cpu].count) - udelay(FLUSH_DELAY); - - preempt_enable(); -} - void smp_flush_tlb_all (void) { diff --git a/trunk/arch/ia64/kernel/topology.c b/trunk/arch/ia64/kernel/topology.c index 94ae3c87d828..687500ddb4b8 100644 --- a/trunk/arch/ia64/kernel/topology.c +++ b/trunk/arch/ia64/kernel/topology.c @@ -412,11 +412,9 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cache_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cache_remove_dev(sys_dev); break; } diff --git a/trunk/arch/ia64/kernel/traps.c b/trunk/arch/ia64/kernel/traps.c index b8e0d70bf989..5bfb8be02b70 100644 --- a/trunk/arch/ia64/kernel/traps.c +++ b/trunk/arch/ia64/kernel/traps.c @@ -43,9 +43,9 @@ die (const char *str, struct pt_regs *regs, long err) u32 lock_owner; int lock_owner_depth; } die = { - .lock = __SPIN_LOCK_UNLOCKED(die.lock), - .lock_owner = -1, - .lock_owner_depth = 0 + .lock = SPIN_LOCK_UNLOCKED, + .lock_owner = -1, + .lock_owner_depth = 0 }; static int die_counter; int cpu = get_cpu(); diff --git a/trunk/arch/ia64/kernel/unwind.c b/trunk/arch/ia64/kernel/unwind.c index fe1426266b9b..93d5a3b41f69 100644 --- a/trunk/arch/ia64/kernel/unwind.c +++ b/trunk/arch/ia64/kernel/unwind.c @@ -60,7 +60,6 @@ # define UNW_DEBUG_ON(n) unw_debug_level >= n /* Do not code a printk level, not all debug lines end in newline */ # define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) -# undef inline # define inline #else /* !UNW_DEBUG */ # define UNW_DEBUG_ON(n) 0 @@ -146,7 +145,7 @@ static struct { # endif } unw = { .tables = &unw.kernel_table, - .lock = __SPIN_LOCK_UNLOCKED(unw.lock), + .lock = SPIN_LOCK_UNLOCKED, .save_order = { UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR, UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR @@ -1944,9 +1943,9 @@ EXPORT_SYMBOL(unw_unwind); int unw_unwind_to_user (struct unw_frame_info *info) { - unsigned long ip, sp, pr = info->pr; + unsigned long ip, sp, pr = 0; - do { + while (unw_unwind(info) >= 0) { unw_get_sp(info, &sp); if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp) < IA64_PT_REGS_SIZE) { @@ -1964,7 +1963,7 @@ unw_unwind_to_user (struct unw_frame_info *info) __FUNCTION__, ip); return -1; } - } while (unw_unwind(info) >= 0); + } unw_get_ip(info, &ip); UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); diff --git a/trunk/arch/ia64/mm/tlb.c b/trunk/arch/ia64/mm/tlb.c index fa4e6d4810f3..ffad7624436c 100644 --- a/trunk/arch/ia64/mm/tlb.c +++ b/trunk/arch/ia64/mm/tlb.c @@ -32,9 +32,9 @@ static struct { } purge; struct ia64_ctx ia64_ctx = { - .lock = __SPIN_LOCK_UNLOCKED(ia64_ctx.lock), - .next = 1, - .max_ctx = ~0U + .lock = SPIN_LOCK_UNLOCKED, + .next = 1, + .max_ctx = ~0U }; DEFINE_PER_CPU(u8, ia64_need_tlb_flush); diff --git a/trunk/arch/ia64/sn/kernel/irq.c b/trunk/arch/ia64/sn/kernel/irq.c index 7f6d2360a262..8d2a1bfbfe7c 100644 --- a/trunk/arch/ia64/sn/kernel/irq.c +++ b/trunk/arch/ia64/sn/kernel/irq.c @@ -59,22 +59,6 @@ void sn_intr_free(nasid_t local_nasid, int local_widget, (u64) sn_irq_info->irq_cookie, 0, 0); } -u64 sn_intr_redirect(nasid_t local_nasid, int local_widget, - struct sn_irq_info *sn_irq_info, - nasid_t req_nasid, int req_slice) -{ - struct ia64_sal_retval ret_stuff; - ret_stuff.status = 0; - ret_stuff.v0 = 0; - - SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, - (u64) SAL_INTR_REDIRECT, (u64) local_nasid, - (u64) local_widget, __pa(sn_irq_info), - (u64) req_nasid, (u64) req_slice, 0); - - return ret_stuff.status; -} - static unsigned int sn_startup_irq(unsigned int irq) { return 0; @@ -143,8 +127,15 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, struct sn_irq_info *new_irq_info; struct sn_pcibus_provider *pci_provider; - bridge = (u64) sn_irq_info->irq_bridge; + new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); + if (new_irq_info == NULL) + return NULL; + + memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); + + bridge = (u64) new_irq_info->irq_bridge; if (!bridge) { + kfree(new_irq_info); return NULL; /* irq is not a device interrupt */ } @@ -154,25 +145,8 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, local_widget = TIO_SWIN_WIDGETNUM(bridge); else local_widget = SWIN_WIDGETNUM(bridge); - vector = sn_irq_info->irq_irq; - - /* Make use of SAL_INTR_REDIRECT if PROM supports it */ - status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice); - if (!status) { - new_irq_info = sn_irq_info; - goto finish_up; - } - - /* - * PROM does not support SAL_INTR_REDIRECT, or it failed. - * Revert to old method. - */ - new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); - if (new_irq_info == NULL) - return NULL; - - memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); + vector = sn_irq_info->irq_irq; /* Free the old PROM new_irq_info structure */ sn_intr_free(local_nasid, local_widget, new_irq_info); unregister_intr_pda(new_irq_info); @@ -188,18 +162,11 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, return NULL; } - register_intr_pda(new_irq_info); - spin_lock(&sn_irq_info_lock); - list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); - spin_unlock(&sn_irq_info_lock); - call_rcu(&sn_irq_info->rcu, sn_irq_info_free); - - -finish_up: /* Update kernels new_irq_info with new target info */ cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid, new_irq_info->irq_slice); new_irq_info->irq_cpuid = cpuid; + register_intr_pda(new_irq_info); pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; @@ -211,6 +178,11 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, pci_provider && pci_provider->target_interrupt) (pci_provider->target_interrupt)(new_irq_info); + spin_lock(&sn_irq_info_lock); + list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); + spin_unlock(&sn_irq_info_lock); + call_rcu(&sn_irq_info->rcu, sn_irq_info_free); + #ifdef CONFIG_SMP cpuphys = cpu_physical_id(cpuid); set_irq_affinity_info((vector & 0xff), cpuphys, 0); diff --git a/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c b/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c index 5d318b579fb1..601747b1e22a 100644 --- a/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -46,9 +46,6 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); -/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */ -static int sn2_flush_opt = 0; - extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, @@ -79,8 +76,6 @@ struct ptc_stats { unsigned long shub_itc_clocks; unsigned long shub_itc_clocks_max; unsigned long shub_ptc_flushes_not_my_mm; - unsigned long shub_ipi_flushes; - unsigned long shub_ipi_flushes_itc_clocks; }; #define sn2_ptctest 0 @@ -126,18 +121,6 @@ void sn_tlb_migrate_finish(struct mm_struct *mm) flush_tlb_mm(mm); } -static void -sn2_ipi_flush_all_tlb(struct mm_struct *mm) -{ - unsigned long itc; - - itc = ia64_get_itc(); - smp_flush_tlb_cpumask(mm->cpu_vm_mask); - itc = ia64_get_itc() - itc; - __get_cpu_var(ptcstats).shub_ipi_flushes_itc_clocks += itc; - __get_cpu_var(ptcstats).shub_ipi_flushes++; -} - /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range * @mm: mm_struct containing virtual address range @@ -171,12 +154,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; - int active, max_active, deadlock, flush_opt = sn2_flush_opt; - - if (flush_opt > 2) { - sn2_ipi_flush_all_tlb(mm); - return; - } + int active, max_active, deadlock; nodes_clear(nodes_flushed); i = 0; @@ -211,12 +189,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, return; } - if (flush_opt == 2) { - sn2_ipi_flush_all_tlb(mm); - preempt_enable(); - return; - } - itc = ia64_get_itc(); nix = 0; for_each_node_mask(cnode, nodes_flushed) @@ -284,8 +256,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, } if (active >= max_active || i == (nix - 1)) { if ((deadlock = wait_piowc())) { - if (flush_opt == 1) - goto done; sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); if (reset_max_active_on_deadlock()) max_active = 1; @@ -297,7 +267,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, start += (1UL << nbits); } while (start < end); -done: itc2 = ia64_get_itc() - itc2; __get_cpu_var(ptcstats).shub_itc_clocks += itc2; if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) @@ -310,11 +279,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, spin_unlock_irqrestore(PTC_LOCK(shub1), flags); - if (flush_opt == 1 && deadlock) { - __get_cpu_var(ptcstats).deadlocks++; - sn2_ipi_flush_all_tlb(mm); - } - preempt_enable(); } @@ -461,42 +425,24 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) if (!cpu) { seq_printf(file, - "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n"); - seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt); + "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); + seq_printf(file, "# ptctest %d\n", sn2_ptctest); } if (cpu < NR_CPUS && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, stat->shub_ptc_flushes_not_my_mm, - stat->deadlocks2, - stat->shub_ipi_flushes, - 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec); + stat->deadlocks2); } return 0; } -static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data) -{ - int cpu; - char optstr[64]; - - if (copy_from_user(optstr, user, count)) - return -EFAULT; - optstr[count - 1] = '\0'; - sn2_flush_opt = simple_strtoul(optstr, NULL, 0); - - for_each_online_cpu(cpu) - memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats)); - - return count; -} - static struct seq_operations sn2_ptc_seq_ops = { .start = sn2_ptc_seq_start, .next = sn2_ptc_seq_next, @@ -512,7 +458,6 @@ static int sn2_ptc_proc_open(struct inode *inode, struct file *file) static const struct file_operations proc_sn2_ptc_operations = { .open = sn2_ptc_proc_open, .read = seq_read, - .write = sn2_ptc_proc_write, .llseek = seq_lseek, .release = seq_release, }; diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index c3bb8a755b00..9740d6b8ae11 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -241,10 +241,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config SCHED_NO_NO_OMIT_FRAME_POINTER - bool - default y - config PREEMPT bool "Preemptible Kernel" help diff --git a/trunk/arch/m32r/mm/mmu.S b/trunk/arch/m32r/mm/mmu.S index 49a6d16a3d58..8bb74b10dca7 100644 --- a/trunk/arch/m32r/mm/mmu.S +++ b/trunk/arch/m32r/mm/mmu.S @@ -163,8 +163,7 @@ ENTRY(tme_handler) ; pte_data = (unsigned long)pte_val(*pte); ld r2, @r3 ; r2: pte data - and3 r3, r2, #2 ; _PAGE_PRESENT(=2) check - beqz r3, 3f + or3 r2, r2, #2 ; _PAGE_PRESENT(=2) .fillinsn 5: @@ -265,8 +264,11 @@ ENTRY(tme_handler) ; and3 r1, r1, #0xeff ldi r4, #611 ; _KERNPG_TABLE(=611) - bne r1, r4, 3f ; !pmd_bad(*pmd) ? - + beq r1, r4, 4f ; !pmd_bad(*pmd) ? + .fillinsn +3: + ldi r1, #0 ; r1: pte_data = 0 + bra 5f .fillinsn 4: ; pte = pte_offset(pmd, address); @@ -280,10 +282,8 @@ ENTRY(tme_handler) add r4, r3 ; r4: pte ; pte_data = (unsigned long)pte_val(*pte); ld r1, @r4 ; r1: pte_data - and3 r3, r1, #2 ; _PAGE_PRESENT(=2) check - beqz r3, 3f - .fillinsn + ;; set tlb ; r0: address, r1: pte_data, r2: entry ; r3,r4: (free) @@ -295,7 +295,8 @@ ENTRY(tme_handler) and3 r4, r4, #(MMU_CONTEXT_ASID_MASK) or r3, r4 st r3, @r2 - st r1, @(4,r2) ; set_tlb_data(entry, pte_data); + or3 r4, r1, #2 ; _PAGE_PRESENT(=2) + st r4, @(4,r2) ; set_tlb_data(entry, pte_data); ld r4, @sp+ ld r3, @sp+ @@ -305,11 +306,6 @@ ENTRY(tme_handler) ld sp, @sp+ rte - .fillinsn -3: - ldi r1, #2 ; r1: pte_data = 0 | _PAGE_PRESENT(=2) - bra 5b - #else #error unknown isa configuration #endif diff --git a/trunk/arch/m68knommu/Kconfig.debug b/trunk/arch/m68knommu/Kconfig.debug index 9ff47bd09aee..763c9aa0b4fd 100644 --- a/trunk/arch/m68knommu/Kconfig.debug +++ b/trunk/arch/m68knommu/Kconfig.debug @@ -5,7 +5,7 @@ source "lib/Kconfig.debug" config FULLDEBUG bool "Full Symbolic/Source Debugging support" help - Enable debugging symbols on kernel build. + Enable debuging symbols on kernel build. config HIGHPROFILE bool "Use fast second timer for profiling" diff --git a/trunk/arch/m68knommu/kernel/asm-offsets.c b/trunk/arch/m68knommu/kernel/asm-offsets.c index 7cd183d346ef..b988c7bdc6e4 100644 --- a/trunk/arch/m68knommu/kernel/asm-offsets.c +++ b/trunk/arch/m68knommu/kernel/asm-offsets.c @@ -31,7 +31,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 16ecea3c0813..b7cb048bc771 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -956,7 +956,7 @@ choice byte order. These modes require different kernels and a different Linux distribution. In general there is one preferred byteorder for a particular system but some systems are just as commonly used in the - one or the other endianness. + one or the other endianess. config CPU_BIG_ENDIAN bool "Big endian" @@ -1750,7 +1750,7 @@ config ARCH_DISCONTIGMEM_ENABLE bool default y if SGI_IP27 help - Say Y to support efficient handling of discontiguous physical memory, + Say Y to upport efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access) or have huge holes in the physical address space for other reasons. See for more. @@ -1938,7 +1938,7 @@ config KEXEC help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot - but it is independent of the system firmware. And like a reboot + but it is indepedent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. The name comes from the similiarity to the exec system call. diff --git a/trunk/arch/mips/Makefile b/trunk/arch/mips/Makefile index 4892db88a86a..f2f742df32c7 100644 --- a/trunk/arch/mips/Makefile +++ b/trunk/arch/mips/Makefile @@ -92,7 +92,7 @@ cflags-y += -ffreestanding # when fed the toolchain default! # # Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of -# 2006-10-10 don't properly change the predefined symbols if -EB / -EL +# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL # are used, so we kludge that here. A bug has been filed at # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413. # diff --git a/trunk/arch/mips/kernel/asm-offsets.c b/trunk/arch/mips/kernel/asm-offsets.c index 3b27309d54b1..761a779d5c4f 100644 --- a/trunk/arch/mips/kernel/asm-offsets.c +++ b/trunk/arch/mips/kernel/asm-offsets.c @@ -82,7 +82,7 @@ void output_task_defines(void) { text("/* MIPS task_struct offsets. */"); offset("#define TASK_STATE ", struct task_struct, state); - offset("#define TASK_THREAD_INFO ", struct task_struct, stack); + offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info); offset("#define TASK_FLAGS ", struct task_struct, flags); offset("#define TASK_MM ", struct task_struct, mm); offset("#define TASK_PID ", struct task_struct, pid); diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index b361edb83dc6..5dcfab6b288e 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/arch/mips/kernel/smtc.c @@ -560,7 +560,7 @@ void smtc_boot_secondary(int cpu, struct task_struct *idle) write_tc_gpr_sp(__KSTK_TOS(idle)); /* global pointer */ - write_tc_gpr_gp((unsigned long)task_thread_info(idle)); + write_tc_gpr_gp((unsigned long)idle->thread_info); smtc_status |= SMTC_MTC_ACTIVE; write_tc_c0_tchalt(0); diff --git a/trunk/arch/mips/pci/fixup-sb1250.c b/trunk/arch/mips/pci/fixup-sb1250.c index 0ad39e53f7b1..7a7444874e80 100644 --- a/trunk/arch/mips/pci/fixup-sb1250.c +++ b/trunk/arch/mips/pci/fixup-sb1250.c @@ -14,7 +14,7 @@ #include /* - * Set the BCM1250, etc. PCI host bridge's TRDY timeout + * Set the the BCM1250, etc. PCI host bridge's TRDY timeout * to the finite max. */ static void __init quirk_sb1250_pci(struct pci_dev *dev) @@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT, quirk_sb1250_ht); /* - * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max. + * Set the the SP1011 HT/PCI bridge's TRDY timeout to the finite max. */ static void __init quirk_sp1011(struct pci_dev *dev) { diff --git a/trunk/arch/parisc/kernel/asm-offsets.c b/trunk/arch/parisc/kernel/asm-offsets.c index d3b7917a87cb..54fdb959149c 100644 --- a/trunk/arch/parisc/kernel/asm-offsets.c +++ b/trunk/arch/parisc/kernel/asm-offsets.c @@ -54,7 +54,7 @@ int main(void) { - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_STATE, offsetof(struct task_struct, state)); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index ccc5410af996..808d2ef80e2f 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -120,6 +120,19 @@ config GENERIC_BUG config SYS_SUPPORTS_APM_EMULATION bool +# +# Powerpc uses the slab allocator to manage its ptes and the +# page structs of ptes are used for splitting the page table +# lock for configurations supporting more than SPLIT_PTLOCK_CPUS. +# +# In that special configuration the page structs of slabs are modified. +# This setting disables the selection of SLUB as a slab allocator. +# +config ARCH_USES_SLAB_PAGE_STRUCT + bool + default y + depends on SPLIT_PTLOCK_CPUS <= NR_CPUS + config DEFAULT_UIMAGE bool help @@ -339,11 +352,6 @@ config PPC_STD_MMU_32 def_bool y depends on PPC_STD_MMU && PPC32 -config PPC_MM_SLICES - bool - default y if HUGETLB_PAGE - default n - config VIRT_CPU_ACCOUNTING bool "Deterministic task and CPU time accounting" depends on PPC64 @@ -533,15 +541,9 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES -config PPC_HAS_HASH_64K - bool - depends on PPC64 - default n - config PPC_64K_PAGES bool "64k page size" depends on PPC64 - select PPC_HAS_HASH_64K help This option changes the kernel logical page size to 64k. On machines without processor support for 64k pages, the kernel will simulate diff --git a/trunk/arch/powerpc/Kconfig.debug b/trunk/arch/powerpc/Kconfig.debug index 346cd3befe1e..f70e795c262e 100644 --- a/trunk/arch/powerpc/Kconfig.debug +++ b/trunk/arch/powerpc/Kconfig.debug @@ -32,7 +32,7 @@ config HCALL_STATS depends on PPC_PSERIES && DEBUG_FS help Adds code to keep track of the number of hypervisor calls made and - the amount of time spent in hypervisor calls. Wall time spent in + the amount of time spent in hypervisor callsr. Wall time spent in each call is always calculated, and if available CPU cycles spent are also calculated. A directory named hcall_inst is added at the root of the debugfs filesystem. Within the hcall_inst directory diff --git a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts index 112dd5198fe2..93b760696010 100644 --- a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -146,7 +146,7 @@ interrupt-parent = < &ipic >; interrupts = <42 8>; bus-range = <0 0>; - ranges = <02000000 0 90000000 90000000 0 10000000 + ranges = <02000000 0 a0000000 90000000 0 10000000 42000000 0 80000000 80000000 0 10000000 01000000 0 00000000 d0000000 0 00100000>; clock-frequency = <0>; diff --git a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts index df773fafe9d1..07bcc5194d2b 100644 --- a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -223,7 +223,7 @@ interrupt-parent = < &ipic >; interrupts = <42 8>; bus-range = <0 0>; - ranges = <02000000 0 90000000 90000000 0 10000000 + ranges = <02000000 0 a0000000 a0000000 0 10000000 42000000 0 80000000 80000000 0 10000000 01000000 0 00000000 e2000000 0 00100000>; clock-frequency = <3f940aa>; @@ -284,7 +284,7 @@ interrupts = <42 8>; bus-range = <0 0>; ranges = <02000000 0 b0000000 b0000000 0 10000000 - 42000000 0 a0000000 a0000000 0 10000000 + 42000000 0 90000000 90000000 0 10000000 01000000 0 00000000 e2100000 0 00100000>; clock-frequency = <3f940aa>; #interrupt-cells = <1>; diff --git a/trunk/arch/powerpc/configs/celleb_defconfig b/trunk/arch/powerpc/configs/celleb_defconfig index 91b657b339b4..a1fe97197ead 100644 --- a/trunk/arch/powerpc/configs/celleb_defconfig +++ b/trunk/arch/powerpc/configs/celleb_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21 -# Tue May 8 12:32:16 2007 +# Linux kernel version: 2.6.20-rc4 +# Thu Jan 11 20:55:33 2007 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -60,7 +60,6 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_IPC_NS is not set -CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set @@ -71,7 +70,6 @@ CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y @@ -134,26 +132,15 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PSERIES is not set # CONFIG_PPC_ISERIES is not set # CONFIG_PPC_MPC52xx is not set -# CONFIG_PPC_MPC5200 is not set # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set # CONFIG_PPC_PASEMI is not set -CONFIG_PPC_CELLEB=y -# CONFIG_PPC_PS3 is not set CONFIG_PPC_CELL=y # CONFIG_PPC_CELL_NATIVE is not set # CONFIG_PPC_IBM_CELL_BLADE is not set - -# -# Cell Broadband Engine options -# -CONFIG_SPU_FS=y -CONFIG_SPU_BASE=y -# CONFIG_PQ2ADS is not set +# CONFIG_PPC_PS3 is not set +CONFIG_PPC_CELLEB=y CONFIG_PPC_UDBG_BEAT=y -# CONFIG_MPIC is not set -# CONFIG_MPIC_WEIRD is not set -# CONFIG_PPC_I8259 is not set # CONFIG_U3_DART is not set # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set @@ -162,7 +149,15 @@ CONFIG_PPC_UDBG_BEAT=y # CONFIG_PPC_INDIRECT_IO is not set # CONFIG_GENERIC_IOMAP is not set # CONFIG_CPU_FREQ is not set -# CONFIG_CPM2 is not set +# CONFIG_WANT_EARLY_SERIAL is not set +# CONFIG_MPIC is not set + +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=y +CONFIG_SPU_BASE=y +# CONFIG_CBE_RAS is not set # # Kernel options @@ -188,6 +183,7 @@ CONFIG_NUMA=y CONFIG_NODES_SHIFT=4 CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set @@ -203,7 +199,6 @@ CONFIG_MEMORY_HOTPLUG_SPARSE=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y -CONFIG_ZONE_DMA_FLAG=1 CONFIG_ARCH_MEMORY_PROBE=y CONFIG_NODES_SPAN_OTHER_NODES=y # CONFIG_PPC_64K_PAGES is not set @@ -212,14 +207,14 @@ CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set # CONFIG_PM is not set CONFIG_SECCOMP=y -# CONFIG_WANT_DEVICE_TREE is not set CONFIG_ISA_DMA_API=y # # Bus options # -CONFIG_ZONE_DMA=y CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set # CONFIG_PPC_INDIRECT_PCI is not set CONFIG_PCI=y CONFIG_PCI_DOMAINS=y @@ -245,13 +240,13 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -267,7 +262,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y +# CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y @@ -285,7 +280,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m @@ -308,21 +302,17 @@ CONFIG_NETFILTER=y # # CONFIG_NETFILTER_NETLINK is not set # CONFIG_NF_CONNTRACK_ENABLED is not set -# CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set # # IP: Netfilter Configuration # CONFIG_IP_NF_QUEUE=m -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set # # IPv6: Netfilter Configuration (EXPERIMENTAL) # # CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_IPTABLES is not set # # DCCP Configuration (EXPERIMENTAL) @@ -362,13 +352,6 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set # CONFIG_IEEE80211 is not set # @@ -382,13 +365,16 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker # # CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# # CONFIG_MTD is not set # @@ -399,7 +385,6 @@ CONFIG_FW_LOADER=y # # Plug and Play support # -# CONFIG_PNPACPI is not set # # Block devices @@ -419,6 +404,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=131072 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -457,6 +443,7 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set @@ -471,7 +458,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -482,11 +468,11 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_TC86C001 is not set -CONFIG_BLK_DEV_CELLEB=y +CONFIG_BLK_DEV_IDE_CELLEB=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -560,7 +546,6 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_ESP_CORE is not set # CONFIG_SCSI_SRP is not set # @@ -606,7 +591,12 @@ CONFIG_DM_MULTIPATH=m # I2O device support # # CONFIG_I2O is not set -# CONFIG_MACINTOSH_DRIVERS is not set + +# +# Macintosh device drivers +# +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set # # Network device support @@ -662,18 +652,15 @@ CONFIG_MII=y # CONFIG_BNX2 is not set CONFIG_SPIDER_NET=y # CONFIG_QLA3XXX is not set -# CONFIG_ATL1 is not set # # Ethernet (10000 Mbit) # # CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set -# CONFIG_PASEMI_MAC is not set # # Token Ring devices @@ -681,10 +668,9 @@ CONFIG_SPIDER_NET=y # CONFIG_TR is not set # -# Wireless LAN +# Wireless LAN (non-hamradio) # -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces @@ -784,7 +770,6 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_TXX9=y CONFIG_HAS_TXX9_SERIAL=y -CONFIG_SERIAL_TXX9_NR_UARTS=3 CONFIG_SERIAL_TXX9_CONSOLE=y # CONFIG_SERIAL_TXX9_STDSERIAL is not set # CONFIG_SERIAL_JSM is not set @@ -905,11 +890,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_HWMON is not set # CONFIG_HWMON_VID is not set -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - # # Multimedia devices # @@ -924,7 +904,7 @@ CONFIG_I2C_ALGOBIT=y # # Graphics support # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FIRMWARE_EDID is not set # CONFIG_FB is not set # CONFIG_FB_IBM_GXT4500 is not set @@ -933,6 +913,7 @@ CONFIG_I2C_ALGOBIT=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -943,15 +924,6 @@ CONFIG_DUMMY_CONSOLE=y # HID Devices # CONFIG_HID=y -# CONFIG_HID_DEBUG is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y # # USB support @@ -966,8 +938,9 @@ CONFIG_USB=y # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_MULTITHREAD_PROBE is not set # CONFIG_USB_OTG is not set # @@ -980,7 +953,6 @@ CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_OHCI_HCD_PPC_OF is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -1017,6 +989,10 @@ CONFIG_USB_STORAGE=m # # USB Input Devices # +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set # CONFIG_USB_ACECAD is not set @@ -1029,7 +1005,6 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_GTCO is not set # # USB Imaging devices @@ -1067,7 +1042,6 @@ CONFIG_USB_MON=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1078,7 +1052,6 @@ CONFIG_USB_MON=y # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # @@ -1135,10 +1108,6 @@ CONFIG_USB_MON=y # DMA Devices # -# -# Auxiliary Display support -# - # # Virtualization # @@ -1324,8 +1293,6 @@ CONFIG_NLS_ISO8859_15=m # Distributed Lock Manager # # CONFIG_DLM is not set -# CONFIG_UCC_SLOW is not set -# CONFIG_UCC_FAST is not set # # Library routines @@ -1338,8 +1305,7 @@ CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y +CONFIG_IOMAP_COPY=y # # Instrumentation Support @@ -1357,16 +1323,15 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set CONFIG_LOG_BUF_SHIFT=15 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1376,10 +1341,8 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y @@ -1393,7 +1356,6 @@ CONFIG_PPC_EARLY_DEBUG=y # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set -# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set CONFIG_PPC_EARLY_DEBUG_BEAT=y # @@ -1423,10 +1385,8 @@ CONFIG_CRYPTO_TGR192=m # CONFIG_CRYPTO_GF128MUL is not set CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=m -CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set CONFIG_CRYPTO_DES=m -# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_TWOFISH_COMMON=m @@ -1441,7 +1401,6 @@ CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m # diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c index 2cb1d9487796..8f48560b7ee2 100644 --- a/trunk/arch/powerpc/kernel/asm-offsets.c +++ b/trunk/arch/powerpc/kernel/asm-offsets.c @@ -58,7 +58,7 @@ int main(void) #ifdef CONFIG_PPC64 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); #else - DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); #endif /* CONFIG_PPC64 */ @@ -122,18 +122,12 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); - DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); -#ifdef CONFIG_PPC_MM_SLICES - DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct, - context.low_slices_psize)); - DEFINE(PACAHIGHSLICEPSIZE, offsetof(struct paca_struct, - context.high_slices_psize)); - DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def)); - DEFINE(MMUPSIZESLLP, offsetof(struct mmu_psize_def, sllp)); -#else DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp)); - -#endif /* CONFIG_PPC_MM_SLICES */ + DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); +#ifdef CONFIG_HUGETLB_PAGE + DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); + DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); +#endif /* CONFIG_HUGETLB_PAGE */ DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 068377a2a8dc..9ed4931af164 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -173,7 +173,7 @@ void local_irq_restore(unsigned long en) lv1_get_version_info(&tmp); } - __hard_irq_enable(); + hard_irq_enable(); } #endif /* CONFIG_PPC64 */ diff --git a/trunk/arch/powerpc/kernel/lparmap.c b/trunk/arch/powerpc/kernel/lparmap.c index af11285ffbd1..584d1e3c013d 100644 --- a/trunk/arch/powerpc/kernel/lparmap.c +++ b/trunk/arch/powerpc/kernel/lparmap.c @@ -10,8 +10,7 @@ #include #include -/* The # is to stop gcc trying to make .text nonexecutable */ -const struct LparMap __attribute__((__section__(".text #"))) xLparMap = { +const struct LparMap __attribute__((__section__(".text"))) xLparMap = { .xNumberEsids = HvEsidsToMap, .xNumberRanges = HvRangesToMap, .xSegmentTableOffs = STAB0_PAGE, diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index b0409e19b1c1..6d05a1f377b5 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -1098,24 +1098,35 @@ static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, unsigned long *start_virt, unsigned long *size) { struct pci_controller *hose = pci_bus_to_host(bus); + struct pci_bus_region region; struct resource *res; - if (bus->self) + if (bus->self) { res = bus->resource[0]; - else + pcibios_resource_to_bus(bus->self, ®ion, res); + *start_phys = hose->io_base_phys + region.start; + *start_virt = (unsigned long) hose->io_base_virt + + region.start; + if (region.end > region.start) + *size = region.end - region.start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, region.start, region.end); + return 1; + } + + } else { /* Root Bus */ res = &hose->io_resource; - - *start_virt = pci_io_base + res->start; - *start_phys = *start_virt + hose->io_base_phys - - (unsigned long) hose->io_base_virt; - - if (res->end > res->start) - *size = res->end - res->start + 1; - else { - printk("%s(): unexpected region 0x%lx->0x%lx\n", - __FUNCTION__, res->start, res->end); - return 1; + *start_phys = hose->io_base_phys + res->start; + *start_virt = (unsigned long) hose->io_base_virt + res->start; + if (res->end > res->start) + *size = res->end - res->start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, res->start, res->end); + return 1; + } } return 0; diff --git a/trunk/arch/powerpc/kernel/prom.c b/trunk/arch/powerpc/kernel/prom.c index c065b5550368..caef555f2dc0 100644 --- a/trunk/arch/powerpc/kernel/prom.c +++ b/trunk/arch/powerpc/kernel/prom.c @@ -716,40 +716,11 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -#ifdef CONFIG_BLK_DEV_INITRD -static void __init early_init_dt_check_for_initrd(unsigned long node) -{ - unsigned long l; - u32 *prop; - - DBG("Looking for initrd properties... "); - - prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); - if (prop) { - initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); - if (prop) { - initrd_end = (unsigned long) - __va(of_read_ulong(prop, l/4)); - initrd_below_start_ok = 1; - } else { - initrd_start = 0; - } - } - - DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); -} -#else -static inline void early_init_dt_check_for_initrd(unsigned long node) -{ -} -#endif /* CONFIG_BLK_DEV_INITRD */ - static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { unsigned long *lprop; + u32 *prop; unsigned long l; char *p; @@ -791,7 +762,21 @@ static int __init early_init_dt_scan_chosen(unsigned long node, crashk_res.end = crashk_res.start + *lprop - 1; #endif - early_init_dt_check_for_initrd(node); +#ifdef CONFIG_BLK_DEV_INITRD + DBG("Looking for initrd properties... "); + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); +#endif /* CONFIG_BLK_DEV_INITRD */ /* Retreive command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); diff --git a/trunk/arch/powerpc/kernel/swsusp.c b/trunk/arch/powerpc/kernel/swsusp.c index 77b7b34b5955..064a7ba4f02c 100644 --- a/trunk/arch/powerpc/kernel/swsusp.c +++ b/trunk/arch/powerpc/kernel/swsusp.c @@ -36,4 +36,8 @@ void restore_processor_state(void) #ifdef CONFIG_PPC32 set_context(current->active_mm->context.id, current->active_mm->pgd); #endif + +#ifdef CONFIG_PPC64 + hard_irq_enable(); +#endif } diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 68991c2d4a1b..cae39d9dfe48 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -342,12 +342,10 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: register_cpu_online(cpu); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: - case CPU_DEAD_FROZEN: unregister_cpu_online(cpu); break; #endif diff --git a/trunk/arch/powerpc/lib/Makefile b/trunk/arch/powerpc/lib/Makefile index 0a486d4b2547..450258de7ca1 100644 --- a/trunk/arch/powerpc/lib/Makefile +++ b/trunk/arch/powerpc/lib/Makefile @@ -23,5 +23,7 @@ obj-$(CONFIG_SMP) += locks.o endif # Temporary hack until we have migrated to asm-powerpc +ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_8xx) += rheap.o obj-$(CONFIG_CPM2) += rheap.o +endif diff --git a/trunk/arch/powerpc/lib/rheap.c b/trunk/arch/powerpc/lib/rheap.c index b2f6dcc59600..6c5c5dd183ee 100644 --- a/trunk/arch/powerpc/lib/rheap.c +++ b/trunk/arch/powerpc/lib/rheap.c @@ -133,7 +133,7 @@ static rh_block_t *get_slot(rh_info_t * info) info->empty_slots--; /* Initialize */ - blk->start = 0; + blk->start = NULL; blk->size = 0; blk->owner = NULL; @@ -158,7 +158,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) /* We assume that they are aligned properly */ size = blkn->size; - s = blkn->start; + s = (unsigned long)blkn->start; e = s + size; /* Find the blocks immediately before and after the given one @@ -170,7 +170,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) list_for_each(l, &info->free_list) { blk = list_entry(l, rh_block_t, list); - bs = blk->start; + bs = (unsigned long)blk->start; be = bs + blk->size; if (next == NULL && s >= bs) @@ -188,10 +188,10 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) } /* Now check if they are really adjacent */ - if (before && s != (before->start + before->size)) + if (before != NULL && s != (unsigned long)before->start + before->size) before = NULL; - if (after && e != after->start) + if (after != NULL && e != (unsigned long)after->start) after = NULL; /* No coalescing; list insert and return */ @@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) /* Grow the after block backwards */ if (before == NULL && after != NULL) { - after->start -= size; + after->start = (int8_t *)after->start - size; after->size += size; return; } @@ -321,14 +321,14 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks, } /* Attach a free memory region, coalesces regions if adjuscent */ -int rh_attach_region(rh_info_t * info, unsigned long start, int size) +int rh_attach_region(rh_info_t * info, void *start, int size) { rh_block_t *blk; unsigned long s, e, m; int r; /* The region must be aligned */ - s = start; + s = (unsigned long)start; e = s + size; m = info->alignment - 1; @@ -338,12 +338,9 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size) /* Round end down */ e = e & ~m; - if (IS_ERR_VALUE(e) || (e < s)) - return -ERANGE; - /* Take final values */ - start = s; - size = e - s; + start = (void *)s; + size = (int)(e - s); /* Grow the blocks, if needed */ r = assure_empty(info, 1); @@ -361,7 +358,7 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size) } /* Detatch given address range, splits free block if needed. */ -unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) +void *rh_detach_region(rh_info_t * info, void *start, int size) { struct list_head *l; rh_block_t *blk, *newblk; @@ -369,10 +366,10 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) /* Validate size */ if (size <= 0) - return (unsigned long) -EINVAL; + return ERR_PTR(-EINVAL); /* The region must be aligned */ - s = start; + s = (unsigned long)start; e = s + size; m = info->alignment - 1; @@ -383,34 +380,34 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) e = e & ~m; if (assure_empty(info, 1) < 0) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); blk = NULL; list_for_each(l, &info->free_list) { blk = list_entry(l, rh_block_t, list); /* The range must lie entirely inside one free block */ - bs = blk->start; - be = blk->start + blk->size; + bs = (unsigned long)blk->start; + be = (unsigned long)blk->start + blk->size; if (s >= bs && e <= be) break; blk = NULL; } if (blk == NULL) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); /* Perfect fit */ if (bs == s && be == e) { /* Delete from free list, release slot */ list_del(&blk->list); release_slot(info, blk); - return s; + return (void *)s; } /* blk still in free list, with updated start and/or size */ if (bs == s || be == e) { if (bs == s) - blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; } else { @@ -419,29 +416,25 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) /* the back free fragment */ newblk = get_slot(info); - newblk->start = e; + newblk->start = (void *)e; newblk->size = be - e; list_add(&newblk->list, &blk->list); } - return s; + return (void *)s; } -/* Allocate a block of memory at the specified alignment. The value returned - * is an offset into the buffer initialized by rh_init(), or a negative number - * if there is an error. - */ -unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner) +void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner) { struct list_head *l; rh_block_t *blk; rh_block_t *newblk; - unsigned long start; + void *start; - /* Validate size, and alignment must be power of two */ + /* Validate size, (must be power of two) */ if (size <= 0 || (alignment & (alignment - 1)) != 0) - return (unsigned long) -EINVAL; + return ERR_PTR(-EINVAL); /* given alignment larger that default rheap alignment */ if (alignment > info->alignment) @@ -451,7 +444,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch size = (size + (info->alignment - 1)) & ~(info->alignment - 1); if (assure_empty(info, 1) < 0) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); blk = NULL; list_for_each(l, &info->free_list) { @@ -462,7 +455,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch } if (blk == NULL) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); /* Just fits */ if (blk->size == size) { @@ -482,7 +475,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch newblk->owner = owner; /* blk still in free list, with updated start, size */ - blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; start = newblk->start; @@ -493,25 +486,19 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch /* this is no problem with the deallocator since */ /* we scan for pointers that lie in the blocks */ if (alignment > info->alignment) - start = (start + alignment - 1) & ~(alignment - 1); + start = (void *)(((unsigned long)start + alignment - 1) & + ~(alignment - 1)); return start; } -/* Allocate a block of memory at the default alignment. The value returned is - * an offset into the buffer initialized by rh_init(), or a negative number if - * there is an error. - */ -unsigned long rh_alloc(rh_info_t * info, int size, const char *owner) +void *rh_alloc(rh_info_t * info, int size, const char *owner) { return rh_alloc_align(info, size, info->alignment, owner); } -/* Allocate a block of memory at the given offset, rounded up to the default - * alignment. The value returned is an offset into the buffer initialized by - * rh_init(), or a negative number if there is an error. - */ -unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner) +/* allocate at precisely the given address */ +void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) { struct list_head *l; rh_block_t *blk, *newblk1, *newblk2; @@ -519,10 +506,10 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co /* Validate size */ if (size <= 0) - return (unsigned long) -EINVAL; + return ERR_PTR(-EINVAL); /* The region must be aligned */ - s = start; + s = (unsigned long)start; e = s + size; m = info->alignment - 1; @@ -533,20 +520,20 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co e = e & ~m; if (assure_empty(info, 2) < 0) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); blk = NULL; list_for_each(l, &info->free_list) { blk = list_entry(l, rh_block_t, list); /* The range must lie entirely inside one free block */ - bs = blk->start; - be = blk->start + blk->size; + bs = (unsigned long)blk->start; + be = (unsigned long)blk->start + blk->size; if (s >= bs && e <= be) break; } if (blk == NULL) - return (unsigned long) -ENOMEM; + return ERR_PTR(-ENOMEM); /* Perfect fit */ if (bs == s && be == e) { @@ -564,7 +551,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co /* blk still in free list, with updated start and/or size */ if (bs == s || be == e) { if (bs == s) - blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; } else { @@ -573,14 +560,14 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co /* The back free fragment */ newblk2 = get_slot(info); - newblk2->start = e; + newblk2->start = (void *)e; newblk2->size = be - e; list_add(&newblk2->list, &blk->list); } newblk1 = get_slot(info); - newblk1->start = s; + newblk1->start = (void *)s; newblk1->size = e - s; newblk1->owner = owner; @@ -590,11 +577,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co return start; } -/* Deallocate the memory previously allocated by one of the rh_alloc functions. - * The return value is the size of the deallocated block, or a negative number - * if there is an error. - */ -int rh_free(rh_info_t * info, unsigned long start) +int rh_free(rh_info_t * info, void *start) { rh_block_t *blk, *blk2; struct list_head *l; @@ -659,7 +642,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) return nr; } -int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) +int rh_set_owner(rh_info_t * info, void *start, const char *owner) { rh_block_t *blk, *blk2; struct list_head *l; @@ -701,8 +684,8 @@ void rh_dump(rh_info_t * info) nr = maxnr; for (i = 0; i < nr; i++) printk(KERN_INFO - " 0x%lx-0x%lx (%u)\n", - st[i].start, st[i].start + st[i].size, + " 0x%p-0x%p (%u)\n", + st[i].start, (int8_t *) st[i].start + st[i].size, st[i].size); printk(KERN_INFO "\n"); @@ -712,8 +695,8 @@ void rh_dump(rh_info_t * info) nr = maxnr; for (i = 0; i < nr; i++) printk(KERN_INFO - " 0x%lx-0x%lx (%u) %s\n", - st[i].start, st[i].start + st[i].size, + " 0x%p-0x%p (%u) %s\n", + st[i].start, (int8_t *) st[i].start + st[i].size, st[i].size, st[i].owner != NULL ? st[i].owner : ""); printk(KERN_INFO "\n"); } @@ -721,6 +704,6 @@ void rh_dump(rh_info_t * info) void rh_dump_blk(rh_info_t * info, rh_block_t * blk) { printk(KERN_INFO - "blk @0x%p: 0x%lx-0x%lx (%u)\n", - blk, blk->start, blk->start + blk->size, blk->size); + "blk @0x%p: 0x%p-0x%p (%u)\n", + blk, blk->start, (int8_t *) blk->start + blk->size, blk->size); } diff --git a/trunk/arch/powerpc/mm/Makefile b/trunk/arch/powerpc/mm/Makefile index 4f839c6a9768..38a81967ca07 100644 --- a/trunk/arch/powerpc/mm/Makefile +++ b/trunk/arch/powerpc/mm/Makefile @@ -18,5 +18,4 @@ obj-$(CONFIG_40x) += 4xx_mmu.o obj-$(CONFIG_44x) += 44x_mmu.o obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o -obj-$(CONFIG_PPC_MM_SLICES) += slice.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/trunk/arch/powerpc/mm/hash_low_64.S b/trunk/arch/powerpc/mm/hash_low_64.S index 4762ff7c14df..e64ce3eec36e 100644 --- a/trunk/arch/powerpc/mm/hash_low_64.S +++ b/trunk/arch/powerpc/mm/hash_low_64.S @@ -615,9 +615,6 @@ htab_pte_insert_failure: li r3,-1 b htab_bail -#endif /* CONFIG_PPC_64K_PAGES */ - -#ifdef CONFIG_PPC_HAS_HASH_64K /***************************************************************************** * * @@ -873,7 +870,7 @@ ht64_pte_insert_failure: b ht64_bail -#endif /* CONFIG_PPC_HAS_HASH_64K */ +#endif /* CONFIG_PPC_64K_PAGES */ /***************************************************************************** diff --git a/trunk/arch/powerpc/mm/hash_native_64.c b/trunk/arch/powerpc/mm/hash_native_64.c index 7d722eea4ea8..7b7fe2d7b9dc 100644 --- a/trunk/arch/powerpc/mm/hash_native_64.c +++ b/trunk/arch/powerpc/mm/hash_native_64.c @@ -376,28 +376,31 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, } } - /* This works for all page sizes, and for 256M and 1T segments */ + /* + * FIXME, the code below works for 16M, 64K, and 4K pages as these + * fall under the p<=23 rules for calculating the virtual address. + * In the case of 16M pages, an extra bit is stolen from the AVPN + * field to achieve the requisite 24 bits. + * + * Does not work for 16G pages or 1 TB segments. + */ shift = mmu_psize_defs[size].shift; - avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23; + if (mmu_psize_defs[size].avpnm) + avpnm_bits = __ilog2_u64(mmu_psize_defs[size].avpnm) + 1; + else + avpnm_bits = 0; + if (shift - avpnm_bits <= 23) { + avpn = HPTE_V_AVPN_VAL(hpte_v) << 23; - if (shift < 23) { - unsigned long vpi, vsid, pteg; + if (shift < 23) { + unsigned long vpi, pteg; - pteg = slot / HPTES_PER_GROUP; - if (hpte_v & HPTE_V_SECONDARY) - pteg = ~pteg; - switch (hpte_v >> HPTE_V_SSIZE_SHIFT) { - case MMU_SEGSIZE_256M: + pteg = slot / HPTES_PER_GROUP; + if (hpte_v & HPTE_V_SECONDARY) + pteg = ~pteg; vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask; - break; - case MMU_SEGSIZE_1T: - vsid = avpn >> 40; - vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask; - break; - default: - avpn = vpi = psize = 0; + avpn |= (vpi << mmu_psize_defs[size].shift); } - avpn |= (vpi << mmu_psize_defs[size].shift); } *va = avpn; diff --git a/trunk/arch/powerpc/mm/hash_utils_64.c b/trunk/arch/powerpc/mm/hash_utils_64.c index 028ba4ed03d2..9b226fa7006f 100644 --- a/trunk/arch/powerpc/mm/hash_utils_64.c +++ b/trunk/arch/powerpc/mm/hash_utils_64.c @@ -51,7 +51,6 @@ #include #include #include -#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -420,7 +419,7 @@ static void __init htab_finish_init(void) extern unsigned int *htab_call_hpte_remove; extern unsigned int *htab_call_hpte_updatepp; -#ifdef CONFIG_PPC_HAS_HASH_64K +#ifdef CONFIG_PPC_64K_PAGES extern unsigned int *ht64_call_hpte_insert1; extern unsigned int *ht64_call_hpte_insert2; extern unsigned int *ht64_call_hpte_remove; @@ -597,23 +596,22 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) * Demote a segment to using 4k pages. * For now this makes the whole process use 4k pages. */ -#ifdef CONFIG_PPC_64K_PAGES -static void demote_segment_4k(struct mm_struct *mm, unsigned long addr) +void demote_segment_4k(struct mm_struct *mm, unsigned long addr) { +#ifdef CONFIG_PPC_64K_PAGES if (mm->context.user_psize == MMU_PAGE_4K) return; -#ifdef CONFIG_PPC_MM_SLICES - slice_set_user_psize(mm, MMU_PAGE_4K); -#else /* CONFIG_PPC_MM_SLICES */ mm->context.user_psize = MMU_PAGE_4K; mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; -#endif /* CONFIG_PPC_MM_SLICES */ - + get_paca()->context = mm->context; + slb_flush_and_rebolt(); #ifdef CONFIG_SPE_BASE spu_flush_all_slbs(mm); #endif +#endif } -#endif /* CONFIG_PPC_64K_PAGES */ + +EXPORT_SYMBOL_GPL(demote_segment_4k); /* Result code is: * 0 - handled @@ -648,11 +646,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) return 1; } vsid = get_vsid(mm->context.id, ea); -#ifdef CONFIG_PPC_MM_SLICES - psize = get_slice_psize(mm, ea); -#else psize = mm->context.user_psize; -#endif break; case VMALLOC_REGION_ID: mm = &init_mm; @@ -680,22 +674,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) local = 1; -#ifdef CONFIG_HUGETLB_PAGE /* Handle hugepage regions */ - if (HPAGE_SHIFT && psize == mmu_huge_psize) { + if (unlikely(in_hugepage_area(mm->context, ea))) { DBG_LOW(" -> huge page !\n"); return hash_huge_page(mm, access, ea, vsid, local, trap); } -#endif /* CONFIG_HUGETLB_PAGE */ - -#ifndef CONFIG_PPC_64K_PAGES - /* If we use 4K pages and our psize is not 4K, then we are hitting - * a special driver mapping, we need to align the address before - * we fetch the PTE - */ - if (psize != MMU_PAGE_4K) - ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); -#endif /* CONFIG_PPC_64K_PAGES */ /* Get PTE and page size from page tables */ ptep = find_linux_pte(pgdir, ea); @@ -719,56 +702,54 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) } /* Do actual hashing */ -#ifdef CONFIG_PPC_64K_PAGES +#ifndef CONFIG_PPC_64K_PAGES + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */ if (pte_val(*ptep) & _PAGE_4K_PFN) { demote_segment_4k(mm, ea); psize = MMU_PAGE_4K; } - /* If this PTE is non-cacheable and we have restrictions on - * using non cacheable large pages, then we switch to 4k - */ - if (mmu_ci_restrictions && psize == MMU_PAGE_64K && - (pte_val(*ptep) & _PAGE_NO_CACHE)) { - if (user_region) { - demote_segment_4k(mm, ea); - psize = MMU_PAGE_4K; - } else if (ea < VMALLOC_END) { - /* - * some driver did a non-cacheable mapping - * in vmalloc space, so switch vmalloc - * to 4k pages - */ - printk(KERN_ALERT "Reducing vmalloc segment " - "to 4kB pages because of " - "non-cacheable mapping\n"); - psize = mmu_vmalloc_psize = MMU_PAGE_4K; + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) { + if (user_region) { + demote_segment_4k(mm, ea); + psize = MMU_PAGE_4K; + } else if (ea < VMALLOC_END) { + /* + * some driver did a non-cacheable mapping + * in vmalloc space, so switch vmalloc + * to 4k pages + */ + printk(KERN_ALERT "Reducing vmalloc segment " + "to 4kB pages because of " + "non-cacheable mapping\n"); + psize = mmu_vmalloc_psize = MMU_PAGE_4K; + } #ifdef CONFIG_SPE_BASE spu_flush_all_slbs(mm); #endif } - } - if (user_region) { - if (psize != get_paca()->context.user_psize) { - get_paca()->context.user_psize = - mm->context.user_psize; + if (user_region) { + if (psize != get_paca()->context.user_psize) { + get_paca()->context = mm->context; + slb_flush_and_rebolt(); + } + } else if (get_paca()->vmalloc_sllp != + mmu_psize_defs[mmu_vmalloc_psize].sllp) { + get_paca()->vmalloc_sllp = + mmu_psize_defs[mmu_vmalloc_psize].sllp; slb_flush_and_rebolt(); } - } else if (get_paca()->vmalloc_sllp != - mmu_psize_defs[mmu_vmalloc_psize].sllp) { - get_paca()->vmalloc_sllp = - mmu_psize_defs[mmu_vmalloc_psize].sllp; - slb_flush_and_rebolt(); } -#endif /* CONFIG_PPC_64K_PAGES */ - -#ifdef CONFIG_PPC_HAS_HASH_64K if (psize == MMU_PAGE_64K) rc = __hash_page_64K(ea, access, vsid, ptep, trap, local); else -#endif /* CONFIG_PPC_HAS_HASH_64K */ rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#endif /* CONFIG_PPC_64K_PAGES */ #ifndef CONFIG_PPC_64K_PAGES DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep)); @@ -791,55 +772,42 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, unsigned long flags; int local = 0; - BUG_ON(REGION_ID(ea) != USER_REGION_ID); - -#ifdef CONFIG_PPC_MM_SLICES - /* We only prefault standard pages for now */ - if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize)); + /* We don't want huge pages prefaulted for now + */ + if (unlikely(in_hugepage_area(mm->context, ea))) return; -#endif DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx," " trap=%lx\n", mm, mm->pgd, ea, access, trap); - /* Get Linux PTE if available */ + /* Get PTE, VSID, access mask */ pgdir = mm->pgd; if (pgdir == NULL) return; ptep = find_linux_pte(pgdir, ea); if (!ptep) return; - -#ifdef CONFIG_PPC_64K_PAGES - /* If either _PAGE_4K_PFN or _PAGE_NO_CACHE is set (and we are on - * a 64K kernel), then we don't preload, hash_page() will take - * care of it once we actually try to access the page. - * That way we don't have to duplicate all of the logic for segment - * page size demotion here - */ - if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE)) - return; -#endif /* CONFIG_PPC_64K_PAGES */ - - /* Get VSID */ vsid = get_vsid(mm->context.id, ea); - /* Hash doesn't like irqs */ + /* Hash it in */ local_irq_save(flags); - - /* Is that local to this CPU ? */ mask = cpumask_of_cpu(smp_processor_id()); if (cpus_equal(mm->cpu_vm_mask, mask)) local = 1; - - /* Hash it in */ -#ifdef CONFIG_PPC_HAS_HASH_64K +#ifndef CONFIG_PPC_64K_PAGES + __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (mm->context.user_psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) + demote_segment_4k(mm, ea); + } if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); else -#endif /* CONFIG_PPC_64K_PAGES */ __hash_page_4K(ea, access, vsid, ptep, trap, local); - +#endif /* CONFIG_PPC_64K_PAGES */ local_irq_restore(flags); } diff --git a/trunk/arch/powerpc/mm/hugetlbpage.c b/trunk/arch/powerpc/mm/hugetlbpage.c index 92a1b16fb7e3..fb959264c104 100644 --- a/trunk/arch/powerpc/mm/hugetlbpage.c +++ b/trunk/arch/powerpc/mm/hugetlbpage.c @@ -91,7 +91,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) pgd_t *pg; pud_t *pu; - BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize); + BUG_ON(! in_hugepage_area(mm->context, addr)); addr &= HPAGE_MASK; @@ -119,7 +119,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) pud_t *pu; hugepd_t *hpdp = NULL; - BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize); + BUG_ON(! in_hugepage_area(mm->context, addr)); addr &= HPAGE_MASK; @@ -302,7 +302,7 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb, start = addr; pgd = pgd_offset((*tlb)->mm, addr); do { - BUG_ON(get_slice_psize((*tlb)->mm, addr) != mmu_huge_psize); + BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr)); next = pgd_addr_end(addr, end); if (pgd_none_or_clear_bad(pgd)) continue; @@ -331,13 +331,203 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return __pte(old); } +struct slb_flush_info { + struct mm_struct *mm; + u16 newareas; +}; + +static void flush_low_segments(void *parm) +{ + struct slb_flush_info *fi = parm; + unsigned long i; + + BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_LOW_AREAS); + + if (current->active_mm != fi->mm) + return; + + /* Only need to do anything if this CPU is working in the same + * mm as the one which has changed */ + + /* update the paca copy of the context struct */ + get_paca()->context = current->active_mm->context; + + asm volatile("isync" : : : "memory"); + for (i = 0; i < NUM_LOW_AREAS; i++) { + if (! (fi->newareas & (1U << i))) + continue; + asm volatile("slbie %0" + : : "r" ((i << SID_SHIFT) | SLBIE_C)); + } + asm volatile("isync" : : : "memory"); +} + +static void flush_high_segments(void *parm) +{ + struct slb_flush_info *fi = parm; + unsigned long i, j; + + + BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_HIGH_AREAS); + + if (current->active_mm != fi->mm) + return; + + /* Only need to do anything if this CPU is working in the same + * mm as the one which has changed */ + + /* update the paca copy of the context struct */ + get_paca()->context = current->active_mm->context; + + asm volatile("isync" : : : "memory"); + for (i = 0; i < NUM_HIGH_AREAS; i++) { + if (! (fi->newareas & (1U << i))) + continue; + for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++) + asm volatile("slbie %0" + :: "r" (((i << HTLB_AREA_SHIFT) + + (j << SID_SHIFT)) | SLBIE_C)); + } + asm volatile("isync" : : : "memory"); +} + +static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area) +{ + unsigned long start = area << SID_SHIFT; + unsigned long end = (area+1) << SID_SHIFT; + struct vm_area_struct *vma; + + BUG_ON(area >= NUM_LOW_AREAS); + + /* Check no VMAs are in the region */ + vma = find_vma(mm, start); + if (vma && (vma->vm_start < end)) + return -EBUSY; + + return 0; +} + +static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area) +{ + unsigned long start = area << HTLB_AREA_SHIFT; + unsigned long end = (area+1) << HTLB_AREA_SHIFT; + struct vm_area_struct *vma; + + BUG_ON(area >= NUM_HIGH_AREAS); + + /* Hack, so that each addresses is controlled by exactly one + * of the high or low area bitmaps, the first high area starts + * at 4GB, not 0 */ + if (start == 0) + start = 0x100000000UL; + + /* Check no VMAs are in the region */ + vma = find_vma(mm, start); + if (vma && (vma->vm_start < end)) + return -EBUSY; + + return 0; +} + +static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas) +{ + unsigned long i; + struct slb_flush_info fi; + + BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS); + BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS); + + newareas &= ~(mm->context.low_htlb_areas); + if (! newareas) + return 0; /* The segments we want are already open */ + + for (i = 0; i < NUM_LOW_AREAS; i++) + if ((1 << i) & newareas) + if (prepare_low_area_for_htlb(mm, i) != 0) + return -EBUSY; + + mm->context.low_htlb_areas |= newareas; + + /* the context change must make it to memory before the flush, + * so that further SLB misses do the right thing. */ + mb(); + + fi.mm = mm; + fi.newareas = newareas; + on_each_cpu(flush_low_segments, &fi, 0, 1); + + return 0; +} + +static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas) +{ + struct slb_flush_info fi; + unsigned long i; + + BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS); + BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8) + != NUM_HIGH_AREAS); + + newareas &= ~(mm->context.high_htlb_areas); + if (! newareas) + return 0; /* The areas we want are already open */ + + for (i = 0; i < NUM_HIGH_AREAS; i++) + if ((1 << i) & newareas) + if (prepare_high_area_for_htlb(mm, i) != 0) + return -EBUSY; + + mm->context.high_htlb_areas |= newareas; + + /* the context change must make it to memory before the flush, + * so that further SLB misses do the right thing. */ + mb(); + + fi.mm = mm; + fi.newareas = newareas; + on_each_cpu(flush_high_segments, &fi, 0, 1); + + return 0; +} + +int prepare_hugepage_range(unsigned long addr, unsigned long len, pgoff_t pgoff) +{ + int err = 0; + + if (pgoff & (~HPAGE_MASK >> PAGE_SHIFT)) + return -EINVAL; + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + + if (addr < 0x100000000UL) + err = open_low_hpage_areas(current->mm, + LOW_ESID_MASK(addr, len)); + if ((addr + len) > 0x100000000UL) + err = open_high_hpage_areas(current->mm, + HTLB_AREA_MASK(addr, len)); +#ifdef CONFIG_SPE_BASE + spu_flush_all_slbs(current->mm); +#endif + if (err) { + printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)" + " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n", + addr, len, + LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len)); + return err; + } + + return 0; +} + struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { pte_t *ptep; struct page *page; - if (get_slice_psize(mm, address) != mmu_huge_psize) + if (! in_hugepage_area(mm->context, address)) return ERR_PTR(-EINVAL); ptep = huge_pte_offset(mm, address); @@ -361,13 +551,359 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, return NULL; } +/* Because we have an exclusive hugepage region which lies within the + * normal user address space, we have to take special measures to make + * non-huge mmap()s evade the hugepage reserved regions. */ +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start_addr; + + if (len > TASK_SIZE) + return -ENOMEM; + + /* handle fixed mapping: prevent overlap with huge pages */ + if (flags & MAP_FIXED) { + if (is_hugepage_only_range(mm, addr, len)) + return -EINVAL; + return addr; + } + + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (((TASK_SIZE - len) >= addr) + && (!vma || (addr+len) <= vma->vm_start) + && !is_hugepage_only_range(mm, addr,len)) + return addr; + } + if (len > mm->cached_hole_size) { + start_addr = addr = mm->free_area_cache; + } else { + start_addr = addr = TASK_UNMAPPED_BASE; + mm->cached_hole_size = 0; + } + +full_search: + vma = find_vma(mm, addr); + while (TASK_SIZE - len >= addr) { + BUG_ON(vma && (addr >= vma->vm_end)); + + if (touches_hugepage_low_range(mm, addr, len)) { + addr = ALIGN(addr+1, 1<vm_start) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } + if (addr + mm->cached_hole_size < vma->vm_start) + mm->cached_hole_size = vma->vm_start - addr; + addr = vma->vm_end; + vma = vma->vm_next; + } + + /* Make sure we didn't miss any holes */ + if (start_addr != TASK_UNMAPPED_BASE) { + start_addr = addr = TASK_UNMAPPED_BASE; + mm->cached_hole_size = 0; + goto full_search; + } + return -ENOMEM; +} + +/* + * This mmap-allocator allocates new areas top-down from below the + * stack's low limit (the base): + * + * Because we have an exclusive hugepage region which lies within the + * normal user address space, we have to take special measures to make + * non-huge mmap()s evade the hugepage reserved regions. + */ +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) +{ + struct vm_area_struct *vma, *prev_vma; + struct mm_struct *mm = current->mm; + unsigned long base = mm->mmap_base, addr = addr0; + unsigned long largest_hole = mm->cached_hole_size; + int first_time = 1; + + /* requested length too big for entire address space */ + if (len > TASK_SIZE) + return -ENOMEM; + + /* handle fixed mapping: prevent overlap with huge pages */ + if (flags & MAP_FIXED) { + if (is_hugepage_only_range(mm, addr, len)) + return -EINVAL; + return addr; + } + + /* dont allow allocations above current base */ + if (mm->free_area_cache > base) + mm->free_area_cache = base; + + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start) + && !is_hugepage_only_range(mm, addr,len)) + return addr; + } + + if (len <= largest_hole) { + largest_hole = 0; + mm->free_area_cache = base; + } +try_again: + /* make sure it can fit in the remaining address space */ + if (mm->free_area_cache < len) + goto fail; + + /* either no address requested or cant fit in requested address hole */ + addr = (mm->free_area_cache - len) & PAGE_MASK; + do { +hugepage_recheck: + if (touches_hugepage_low_range(mm, addr, len)) { + addr = (addr & ((~0) << SID_SHIFT)) - len; + goto hugepage_recheck; + } else if (touches_hugepage_high_range(mm, addr, len)) { + addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len; + goto hugepage_recheck; + } + + /* + * Lookup failure means no vma is above this address, + * i.e. return with success: + */ + if (!(vma = find_vma_prev(mm, addr, &prev_vma))) + return addr; + + /* + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ + if (addr+len <= vma->vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) { + /* remember the address as a hint for next time */ + mm->cached_hole_size = largest_hole; + return (mm->free_area_cache = addr); + } else { + /* pull free_area_cache down to the first hole */ + if (mm->free_area_cache == vma->vm_end) { + mm->free_area_cache = vma->vm_start; + mm->cached_hole_size = largest_hole; + } + } + + /* remember the largest hole we saw so far */ + if (addr + largest_hole < vma->vm_start) + largest_hole = vma->vm_start - addr; + + /* try just below the current vma->vm_start */ + addr = vma->vm_start-len; + } while (len <= vma->vm_start); + +fail: + /* + * if hint left us with no space for the requested + * mapping then try again: + */ + if (first_time) { + mm->free_area_cache = base; + largest_hole = 0; + first_time = 0; + goto try_again; + } + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + mm->free_area_cache = TASK_UNMAPPED_BASE; + mm->cached_hole_size = ~0UL; + addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); + /* + * Restore the topdown base: + */ + mm->free_area_cache = base; + mm->cached_hole_size = ~0UL; + + return addr; +} + +static int htlb_check_hinted_area(unsigned long addr, unsigned long len) +{ + struct vm_area_struct *vma; + + vma = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || ((addr + len) <= vma->vm_start))) + return 0; + + return -ENOMEM; +} + +static unsigned long htlb_get_low_area(unsigned long len, u16 segmask) +{ + unsigned long addr = 0; + struct vm_area_struct *vma; + + vma = find_vma(current->mm, addr); + while (addr + len <= 0x100000000UL) { + BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */ + + if (! __within_hugepage_low_range(addr, len, segmask)) { + addr = ALIGN(addr+1, 1<mm, addr); + continue; + } + + if (!vma || (addr + len) <= vma->vm_start) + return addr; + addr = ALIGN(vma->vm_end, HPAGE_SIZE); + /* Depending on segmask this might not be a confirmed + * hugepage region, so the ALIGN could have skipped + * some VMAs */ + vma = find_vma(current->mm, addr); + } + + return -ENOMEM; +} + +static unsigned long htlb_get_high_area(unsigned long len, u16 areamask) +{ + unsigned long addr = 0x100000000UL; + struct vm_area_struct *vma; + + vma = find_vma(current->mm, addr); + while (addr + len <= TASK_SIZE_USER64) { + BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */ + + if (! __within_hugepage_high_range(addr, len, areamask)) { + addr = ALIGN(addr+1, 1UL<mm, addr); + continue; + } + + if (!vma || (addr + len) <= vma->vm_start) + return addr; + addr = ALIGN(vma->vm_end, HPAGE_SIZE); + /* Depending on segmask this might not be a confirmed + * hugepage region, so the ALIGN could have skipped + * some VMAs */ + vma = find_vma(current->mm, addr); + } + + return -ENOMEM; +} unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - return slice_get_unmapped_area(addr, len, flags, - mmu_huge_psize, 1, 0); + int lastshift; + u16 areamask, curareas; + + if (HPAGE_SHIFT == 0) + return -EINVAL; + if (len & ~HPAGE_MASK) + return -EINVAL; + if (len > TASK_SIZE) + return -ENOMEM; + + if (!cpu_has_feature(CPU_FTR_16M_PAGE)) + return -EINVAL; + + /* Paranoia, caller should have dealt with this */ + BUG_ON((addr + len) < addr); + + /* Handle MAP_FIXED */ + if (flags & MAP_FIXED) { + if (prepare_hugepage_range(addr, len, pgoff)) + return -EINVAL; + return addr; + } + + if (test_thread_flag(TIF_32BIT)) { + curareas = current->mm->context.low_htlb_areas; + + /* First see if we can use the hint address */ + if (addr && (htlb_check_hinted_area(addr, len) == 0)) { + areamask = LOW_ESID_MASK(addr, len); + if (open_low_hpage_areas(current->mm, areamask) == 0) + return addr; + } + + /* Next see if we can map in the existing low areas */ + addr = htlb_get_low_area(len, curareas); + if (addr != -ENOMEM) + return addr; + + /* Finally go looking for areas to open */ + lastshift = 0; + for (areamask = LOW_ESID_MASK(0x100000000UL-len, len); + ! lastshift; areamask >>=1) { + if (areamask & 1) + lastshift = 1; + + addr = htlb_get_low_area(len, curareas | areamask); + if ((addr != -ENOMEM) + && open_low_hpage_areas(current->mm, areamask) == 0) + return addr; + } + } else { + curareas = current->mm->context.high_htlb_areas; + + /* First see if we can use the hint address */ + /* We discourage 64-bit processes from doing hugepage + * mappings below 4GB (must use MAP_FIXED) */ + if ((addr >= 0x100000000UL) + && (htlb_check_hinted_area(addr, len) == 0)) { + areamask = HTLB_AREA_MASK(addr, len); + if (open_high_hpage_areas(current->mm, areamask) == 0) + return addr; + } + + /* Next see if we can map in the existing high areas */ + addr = htlb_get_high_area(len, curareas); + if (addr != -ENOMEM) + return addr; + + /* Finally go looking for areas to open */ + lastshift = 0; + for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len); + ! lastshift; areamask >>=1) { + if (areamask & 1) + lastshift = 1; + + addr = htlb_get_high_area(len, curareas | areamask); + if ((addr != -ENOMEM) + && open_high_hpage_areas(current->mm, areamask) == 0) + return addr; + } + } + printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open" + " enough areas\n"); + return -ENOMEM; } /* diff --git a/trunk/arch/powerpc/mm/init_64.c b/trunk/arch/powerpc/mm/init_64.c index 7312a265545f..fe1fe852181a 100644 --- a/trunk/arch/powerpc/mm/init_64.c +++ b/trunk/arch/powerpc/mm/init_64.c @@ -146,16 +146,21 @@ static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) memset(addr, 0, kmem_cache_size(cache)); } -static const unsigned int pgtable_cache_size[2] = { - PGD_TABLE_SIZE, PMD_TABLE_SIZE +#ifdef CONFIG_PPC_64K_PAGES +static const unsigned int pgtable_cache_size[3] = { + PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE }; static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { -#ifdef CONFIG_PPC_64K_PAGES - "pgd_cache", "pmd_cache", + "pte_pmd_cache", "pmd_cache", "pgd_cache", +}; #else - "pgd_cache", "pud_pmd_cache", -#endif /* CONFIG_PPC_64K_PAGES */ +static const unsigned int pgtable_cache_size[2] = { + PTE_TABLE_SIZE, PMD_TABLE_SIZE +}; +static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { + "pgd_pte_cache", "pud_pmd_cache", }; +#endif /* CONFIG_PPC_64K_PAGES */ #ifdef CONFIG_HUGETLB_PAGE /* Hugepages need one extra cache, initialized in hugetlbpage.c. We diff --git a/trunk/arch/powerpc/mm/mem.c b/trunk/arch/powerpc/mm/mem.c index 246eeea40ece..1a6e08f3298f 100644 --- a/trunk/arch/powerpc/mm/mem.c +++ b/trunk/arch/powerpc/mm/mem.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -277,28 +276,6 @@ void __init do_init_bootmem(void) init_bootmem_done = 1; } -/* mark pages that don't exist as nosave */ -static int __init mark_nonram_nosave(void) -{ - unsigned long lmb_next_region_start_pfn, - lmb_region_max_pfn; - int i; - - for (i = 0; i < lmb.memory.cnt - 1; i++) { - lmb_region_max_pfn = - (lmb.memory.region[i].base >> PAGE_SHIFT) + - (lmb.memory.region[i].size >> PAGE_SHIFT); - lmb_next_region_start_pfn = - lmb.memory.region[i+1].base >> PAGE_SHIFT; - - if (lmb_region_max_pfn < lmb_next_region_start_pfn) - register_nosave_region(lmb_region_max_pfn, - lmb_next_region_start_pfn); - } - - return 0; -} - /* * paging_init() sets up the page tables - in fact we've already done this. */ @@ -330,8 +307,6 @@ void __init paging_init(void) max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; #endif free_area_init_nodes(max_zone_pfns); - - mark_nonram_nosave(); } #endif /* ! CONFIG_NEED_MULTIPLE_NODES */ diff --git a/trunk/arch/powerpc/mm/mmu_context_64.c b/trunk/arch/powerpc/mm/mmu_context_64.c index 7a78cdc0515a..90a06ac02d5e 100644 --- a/trunk/arch/powerpc/mm/mmu_context_64.c +++ b/trunk/arch/powerpc/mm/mmu_context_64.c @@ -28,7 +28,6 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { int index; int err; - int new_context = (mm->context.id == 0); again: if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL)) @@ -51,18 +50,9 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) } mm->context.id = index; -#ifdef CONFIG_PPC_MM_SLICES - /* The old code would re-promote on fork, we don't do that - * when using slices as it could cause problem promoting slices - * that have been forced down to 4K - */ - if (new_context) - slice_set_user_psize(mm, mmu_virtual_psize); -#else mm->context.user_psize = mmu_virtual_psize; mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[mmu_virtual_psize].sllp; -#endif return 0; } diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index de45aa82d97b..b3a592b25ab3 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -252,15 +252,12 @@ static int __cpuinit cpu_numa_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: numa_setup_cpu(lcpu); ret = NOTIFY_OK; break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: - case CPU_DEAD_FROZEN: case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: unmap_cpu_from_node(lcpu); break; ret = NOTIFY_OK; diff --git a/trunk/arch/powerpc/mm/ppc_mmu_32.c b/trunk/arch/powerpc/mm/ppc_mmu_32.c index ec1421a20aaa..05066674a7a0 100644 --- a/trunk/arch/powerpc/mm/ppc_mmu_32.c +++ b/trunk/arch/powerpc/mm/ppc_mmu_32.c @@ -185,7 +185,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, if (Hash == 0) return; - pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea); + pmd = pmd_offset(pgd_offset(mm, ea), ea); if (!pmd_none(*pmd)) add_hash_page(mm->context.id, ea, pmd_val(*pmd)); } diff --git a/trunk/arch/powerpc/mm/slb.c b/trunk/arch/powerpc/mm/slb.c index 304375a73574..224e960650a0 100644 --- a/trunk/arch/powerpc/mm/slb.c +++ b/trunk/arch/powerpc/mm/slb.c @@ -198,6 +198,12 @@ void slb_initialize(void) static int slb_encoding_inited; extern unsigned int *slb_miss_kernel_load_linear; extern unsigned int *slb_miss_kernel_load_io; +#ifdef CONFIG_HUGETLB_PAGE + extern unsigned int *slb_miss_user_load_huge; + unsigned long huge_llp; + + huge_llp = mmu_psize_defs[mmu_huge_psize].sllp; +#endif /* Prepare our SLB miss handler based on our page size */ linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; @@ -214,6 +220,11 @@ void slb_initialize(void) DBG("SLB: linear LLP = %04x\n", linear_llp); DBG("SLB: io LLP = %04x\n", io_llp); +#ifdef CONFIG_HUGETLB_PAGE + patch_slb_encoding(slb_miss_user_load_huge, + SLB_VSID_USER | huge_llp); + DBG("SLB: huge LLP = %04x\n", huge_llp); +#endif } get_paca()->stab_rr = SLB_NUM_BOLTED; diff --git a/trunk/arch/powerpc/mm/slb_low.S b/trunk/arch/powerpc/mm/slb_low.S index cd1a93d4948c..b10e4707d7c1 100644 --- a/trunk/arch/powerpc/mm/slb_low.S +++ b/trunk/arch/powerpc/mm/slb_low.S @@ -82,45 +82,31 @@ _GLOBAL(slb_miss_kernel_load_io) srdi. r9,r10,USER_ESID_BITS bne- 8f /* invalid ea bits set */ - - /* when using slices, we extract the psize off the slice bitmaps - * and then we need to get the sllp encoding off the mmu_psize_defs - * array. - * - * XXX This is a bit inefficient especially for the normal case, - * so we should try to implement a fast path for the standard page - * size using the old sllp value so we avoid the array. We cannot - * really do dynamic patching unfortunately as processes might flip - * between 4k and 64k standard page size - */ -#ifdef CONFIG_PPC_MM_SLICES + /* Figure out if the segment contains huge pages */ +#ifdef CONFIG_HUGETLB_PAGE +BEGIN_FTR_SECTION + b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) cmpldi r10,16 - /* Get the slice index * 4 in r11 and matching slice size mask in r9 */ - ld r9,PACALOWSLICESPSIZE(r13) - sldi r11,r10,2 + lhz r9,PACALOWHTLBAREAS(r13) + mr r11,r10 blt 5f - ld r9,PACAHIGHSLICEPSIZE(r13) - srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2) - andi. r11,r11,0x3c -5: /* Extract the psize and multiply to get an array offset */ - srd r9,r9,r11 - andi. r9,r9,0xf - mulli r9,r9,MMUPSIZEDEFSIZE + lhz r9,PACAHIGHHTLBAREAS(r13) + srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT) - /* Now get to the array and obtain the sllp - */ - ld r11,PACATOC(r13) - ld r11,mmu_psize_defs@got(r11) - add r11,r11,r9 - ld r11,MMUPSIZESLLP(r11) - ori r11,r11,SLB_VSID_USER -#else - /* paca context sllp already contains the SLB_VSID_USER bits */ - lhz r11,PACACONTEXTSLLP(r13) -#endif /* CONFIG_PPC_MM_SLICES */ +5: srd r9,r9,r11 + andi. r9,r9,1 + beq 1f +_GLOBAL(slb_miss_user_load_huge) + li r11,0 + b 2f +1: +#endif /* CONFIG_HUGETLB_PAGE */ + lhz r11,PACACONTEXTSLLP(r13) +2: ld r9,PACACONTEXTID(r13) rldimi r10,r9,USER_ESID_BITS,0 b slb_finish_load diff --git a/trunk/arch/powerpc/mm/slice.c b/trunk/arch/powerpc/mm/slice.c deleted file mode 100644 index f833dba2a028..000000000000 --- a/trunk/arch/powerpc/mm/slice.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * address space "slices" (meta-segments) support - * - * Copyright (C) 2007 Benjamin Herrenschmidt, IBM Corporation. - * - * Based on hugetlb implementation - * - * Copyright (C) 2003 David Gibson, 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 - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static spinlock_t slice_convert_lock = SPIN_LOCK_UNLOCKED; - - -#ifdef DEBUG -int _slice_debug = 1; - -static void slice_print_mask(const char *label, struct slice_mask mask) -{ - char *p, buf[16 + 3 + 16 + 1]; - int i; - - if (!_slice_debug) - return; - p = buf; - for (i = 0; i < SLICE_NUM_LOW; i++) - *(p++) = (mask.low_slices & (1 << i)) ? '1' : '0'; - *(p++) = ' '; - *(p++) = '-'; - *(p++) = ' '; - for (i = 0; i < SLICE_NUM_HIGH; i++) - *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0'; - *(p++) = 0; - - printk(KERN_DEBUG "%s:%s\n", label, buf); -} - -#define slice_dbg(fmt...) do { if (_slice_debug) pr_debug(fmt); } while(0) - -#else - -static void slice_print_mask(const char *label, struct slice_mask mask) {} -#define slice_dbg(fmt...) - -#endif - -static struct slice_mask slice_range_to_mask(unsigned long start, - unsigned long len) -{ - unsigned long end = start + len - 1; - struct slice_mask ret = { 0, 0 }; - - if (start < SLICE_LOW_TOP) { - unsigned long mend = min(end, SLICE_LOW_TOP); - unsigned long mstart = min(start, SLICE_LOW_TOP); - - ret.low_slices = (1u << (GET_LOW_SLICE_INDEX(mend) + 1)) - - (1u << GET_LOW_SLICE_INDEX(mstart)); - } - - if ((start + len) > SLICE_LOW_TOP) - ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1)) - - (1u << GET_HIGH_SLICE_INDEX(start)); - - return ret; -} - -static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, - unsigned long len) -{ - struct vm_area_struct *vma; - - if ((mm->task_size - len) < addr) - return 0; - vma = find_vma(mm, addr); - return (!vma || (addr + len) <= vma->vm_start); -} - -static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) -{ - return !slice_area_is_free(mm, slice << SLICE_LOW_SHIFT, - 1ul << SLICE_LOW_SHIFT); -} - -static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice) -{ - unsigned long start = slice << SLICE_HIGH_SHIFT; - unsigned long end = start + (1ul << SLICE_HIGH_SHIFT); - - /* Hack, so that each addresses is controlled by exactly one - * of the high or low area bitmaps, the first high area starts - * at 4GB, not 0 */ - if (start == 0) - start = SLICE_LOW_TOP; - - return !slice_area_is_free(mm, start, end - start); -} - -static struct slice_mask slice_mask_for_free(struct mm_struct *mm) -{ - struct slice_mask ret = { 0, 0 }; - unsigned long i; - - for (i = 0; i < SLICE_NUM_LOW; i++) - if (!slice_low_has_vma(mm, i)) - ret.low_slices |= 1u << i; - - if (mm->task_size <= SLICE_LOW_TOP) - return ret; - - for (i = 0; i < SLICE_NUM_HIGH; i++) - if (!slice_high_has_vma(mm, i)) - ret.high_slices |= 1u << i; - - return ret; -} - -static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize) -{ - struct slice_mask ret = { 0, 0 }; - unsigned long i; - u64 psizes; - - psizes = mm->context.low_slices_psize; - for (i = 0; i < SLICE_NUM_LOW; i++) - if (((psizes >> (i * 4)) & 0xf) == psize) - ret.low_slices |= 1u << i; - - psizes = mm->context.high_slices_psize; - for (i = 0; i < SLICE_NUM_HIGH; i++) - if (((psizes >> (i * 4)) & 0xf) == psize) - ret.high_slices |= 1u << i; - - return ret; -} - -static int slice_check_fit(struct slice_mask mask, struct slice_mask available) -{ - return (mask.low_slices & available.low_slices) == mask.low_slices && - (mask.high_slices & available.high_slices) == mask.high_slices; -} - -static void slice_flush_segments(void *parm) -{ - struct mm_struct *mm = parm; - unsigned long flags; - - if (mm != current->active_mm) - return; - - /* update the paca copy of the context struct */ - get_paca()->context = current->active_mm->context; - - local_irq_save(flags); - slb_flush_and_rebolt(); - local_irq_restore(flags); -} - -static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize) -{ - /* Write the new slice psize bits */ - u64 lpsizes, hpsizes; - unsigned long i, flags; - - slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize); - slice_print_mask(" mask", mask); - - /* We need to use a spinlock here to protect against - * concurrent 64k -> 4k demotion ... - */ - spin_lock_irqsave(&slice_convert_lock, flags); - - lpsizes = mm->context.low_slices_psize; - for (i = 0; i < SLICE_NUM_LOW; i++) - if (mask.low_slices & (1u << i)) - lpsizes = (lpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - - hpsizes = mm->context.high_slices_psize; - for (i = 0; i < SLICE_NUM_HIGH; i++) - if (mask.high_slices & (1u << i)) - hpsizes = (hpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - - mm->context.low_slices_psize = lpsizes; - mm->context.high_slices_psize = hpsizes; - - slice_dbg(" lsps=%lx, hsps=%lx\n", - mm->context.low_slices_psize, - mm->context.high_slices_psize); - - spin_unlock_irqrestore(&slice_convert_lock, flags); - mb(); - - /* XXX this is sub-optimal but will do for now */ - on_each_cpu(slice_flush_segments, mm, 0, 1); -#ifdef CONFIG_SPU_BASE - spu_flush_all_slbs(mm); -#endif -} - -static unsigned long slice_find_area_bottomup(struct mm_struct *mm, - unsigned long len, - struct slice_mask available, - int psize, int use_cache) -{ - struct vm_area_struct *vma; - unsigned long start_addr, addr; - struct slice_mask mask; - int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); - - if (use_cache) { - if (len <= mm->cached_hole_size) { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; - } else - start_addr = addr = mm->free_area_cache; - } else - start_addr = addr = TASK_UNMAPPED_BASE; - -full_search: - for (;;) { - addr = _ALIGN_UP(addr, 1ul << pshift); - if ((TASK_SIZE - len) < addr) - break; - vma = find_vma(mm, addr); - BUG_ON(vma && (addr >= vma->vm_end)); - - mask = slice_range_to_mask(addr, len); - if (!slice_check_fit(mask, available)) { - if (addr < SLICE_LOW_TOP) - addr = _ALIGN_UP(addr + 1, 1ul << SLICE_LOW_SHIFT); - else - addr = _ALIGN_UP(addr + 1, 1ul << SLICE_HIGH_SHIFT); - continue; - } - if (!vma || addr + len <= vma->vm_start) { - /* - * Remember the place where we stopped the search: - */ - if (use_cache) - mm->free_area_cache = addr + len; - return addr; - } - if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; - addr = vma->vm_end; - } - - /* Make sure we didn't miss any holes */ - if (use_cache && start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; - goto full_search; - } - return -ENOMEM; -} - -static unsigned long slice_find_area_topdown(struct mm_struct *mm, - unsigned long len, - struct slice_mask available, - int psize, int use_cache) -{ - struct vm_area_struct *vma; - unsigned long addr; - struct slice_mask mask; - int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); - - /* check if free_area_cache is useful for us */ - if (use_cache) { - if (len <= mm->cached_hole_size) { - mm->cached_hole_size = 0; - mm->free_area_cache = mm->mmap_base; - } - - /* either no address requested or can't fit in requested - * address hole - */ - addr = mm->free_area_cache; - - /* make sure it can fit in the remaining address space */ - if (addr > len) { - addr = _ALIGN_DOWN(addr - len, 1ul << pshift); - mask = slice_range_to_mask(addr, len); - if (slice_check_fit(mask, available) && - slice_area_is_free(mm, addr, len)) - /* remember the address as a hint for - * next time - */ - return (mm->free_area_cache = addr); - } - } - - addr = mm->mmap_base; - while (addr > len) { - /* Go down by chunk size */ - addr = _ALIGN_DOWN(addr - len, 1ul << pshift); - - /* Check for hit with different page size */ - mask = slice_range_to_mask(addr, len); - if (!slice_check_fit(mask, available)) { - if (addr < SLICE_LOW_TOP) - addr = _ALIGN_DOWN(addr, 1ul << SLICE_LOW_SHIFT); - else if (addr < (1ul << SLICE_HIGH_SHIFT)) - addr = SLICE_LOW_TOP; - else - addr = _ALIGN_DOWN(addr, 1ul << SLICE_HIGH_SHIFT); - continue; - } - - /* - * Lookup failure means no vma is above this address, - * else if new region fits below vma->vm_start, - * return with success: - */ - vma = find_vma(mm, addr); - if (!vma || (addr + len) <= vma->vm_start) { - /* remember the address as a hint for next time */ - if (use_cache) - mm->free_area_cache = addr; - return addr; - } - - /* remember the largest hole we saw so far */ - if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; - - /* try just below the current vma->vm_start */ - addr = vma->vm_start; - } - - /* - * A failed mmap() very likely causes application failure, - * so fall back to the bottom-up function here. This scenario - * can happen with large stack limits and large mmap() - * allocations. - */ - addr = slice_find_area_bottomup(mm, len, available, psize, 0); - - /* - * Restore the topdown base: - */ - if (use_cache) { - mm->free_area_cache = mm->mmap_base; - mm->cached_hole_size = ~0UL; - } - - return addr; -} - - -static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len, - struct slice_mask mask, int psize, - int topdown, int use_cache) -{ - if (topdown) - return slice_find_area_topdown(mm, len, mask, psize, use_cache); - else - return slice_find_area_bottomup(mm, len, mask, psize, use_cache); -} - -unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, - unsigned long flags, unsigned int psize, - int topdown, int use_cache) -{ - struct slice_mask mask; - struct slice_mask good_mask; - struct slice_mask potential_mask = {0,0} /* silence stupid warning */; - int pmask_set = 0; - int fixed = (flags & MAP_FIXED); - int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); - struct mm_struct *mm = current->mm; - - /* Sanity checks */ - BUG_ON(mm->task_size == 0); - - slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize); - slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d, use_cache=%d\n", - addr, len, flags, topdown, use_cache); - - if (len > mm->task_size) - return -ENOMEM; - if (fixed && (addr & ((1ul << pshift) - 1))) - return -EINVAL; - if (fixed && addr > (mm->task_size - len)) - return -EINVAL; - - /* If hint, make sure it matches our alignment restrictions */ - if (!fixed && addr) { - addr = _ALIGN_UP(addr, 1ul << pshift); - slice_dbg(" aligned addr=%lx\n", addr); - } - - /* First makeup a "good" mask of slices that have the right size - * already - */ - good_mask = slice_mask_for_size(mm, psize); - slice_print_mask(" good_mask", good_mask); - - /* First check hint if it's valid or if we have MAP_FIXED */ - if ((addr != 0 || fixed) && (mm->task_size - len) >= addr) { - - /* Don't bother with hint if it overlaps a VMA */ - if (!fixed && !slice_area_is_free(mm, addr, len)) - goto search; - - /* Build a mask for the requested range */ - mask = slice_range_to_mask(addr, len); - slice_print_mask(" mask", mask); - - /* Check if we fit in the good mask. If we do, we just return, - * nothing else to do - */ - if (slice_check_fit(mask, good_mask)) { - slice_dbg(" fits good !\n"); - return addr; - } - - /* We don't fit in the good mask, check what other slices are - * empty and thus can be converted - */ - potential_mask = slice_mask_for_free(mm); - potential_mask.low_slices |= good_mask.low_slices; - potential_mask.high_slices |= good_mask.high_slices; - pmask_set = 1; - slice_print_mask(" potential", potential_mask); - if (slice_check_fit(mask, potential_mask)) { - slice_dbg(" fits potential !\n"); - goto convert; - } - } - - /* If we have MAP_FIXED and failed the above step, then error out */ - if (fixed) - return -EBUSY; - - search: - slice_dbg(" search...\n"); - - /* Now let's see if we can find something in the existing slices - * for that size - */ - addr = slice_find_area(mm, len, good_mask, psize, topdown, use_cache); - if (addr != -ENOMEM) { - /* Found within the good mask, we don't have to setup, - * we thus return directly - */ - slice_dbg(" found area at 0x%lx\n", addr); - return addr; - } - - /* Won't fit, check what can be converted */ - if (!pmask_set) { - potential_mask = slice_mask_for_free(mm); - potential_mask.low_slices |= good_mask.low_slices; - potential_mask.high_slices |= good_mask.high_slices; - pmask_set = 1; - slice_print_mask(" potential", potential_mask); - } - - /* Now let's see if we can find something in the existing slices - * for that size - */ - addr = slice_find_area(mm, len, potential_mask, psize, topdown, - use_cache); - if (addr == -ENOMEM) - return -ENOMEM; - - mask = slice_range_to_mask(addr, len); - slice_dbg(" found potential area at 0x%lx\n", addr); - slice_print_mask(" mask", mask); - - convert: - slice_convert(mm, mask, psize); - return addr; - -} -EXPORT_SYMBOL_GPL(slice_get_unmapped_area); - -unsigned long arch_get_unmapped_area(struct file *filp, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ - return slice_get_unmapped_area(addr, len, flags, - current->mm->context.user_psize, - 0, 1); -} - -unsigned long arch_get_unmapped_area_topdown(struct file *filp, - const unsigned long addr0, - const unsigned long len, - const unsigned long pgoff, - const unsigned long flags) -{ - return slice_get_unmapped_area(addr0, len, flags, - current->mm->context.user_psize, - 1, 1); -} - -unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) -{ - u64 psizes; - int index; - - if (addr < SLICE_LOW_TOP) { - psizes = mm->context.low_slices_psize; - index = GET_LOW_SLICE_INDEX(addr); - } else { - psizes = mm->context.high_slices_psize; - index = GET_HIGH_SLICE_INDEX(addr); - } - - return (psizes >> (index * 4)) & 0xf; -} -EXPORT_SYMBOL_GPL(get_slice_psize); - -/* - * This is called by hash_page when it needs to do a lazy conversion of - * an address space from real 64K pages to combo 4K pages (typically - * when hitting a non cacheable mapping on a processor or hypervisor - * that won't allow them for 64K pages). - * - * This is also called in init_new_context() to change back the user - * psize from whatever the parent context had it set to - * - * This function will only change the content of the {low,high)_slice_psize - * masks, it will not flush SLBs as this shall be handled lazily by the - * caller. - */ -void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) -{ - unsigned long flags, lpsizes, hpsizes; - unsigned int old_psize; - int i; - - slice_dbg("slice_set_user_psize(mm=%p, psize=%d)\n", mm, psize); - - spin_lock_irqsave(&slice_convert_lock, flags); - - old_psize = mm->context.user_psize; - slice_dbg(" old_psize=%d\n", old_psize); - if (old_psize == psize) - goto bail; - - mm->context.user_psize = psize; - wmb(); - - lpsizes = mm->context.low_slices_psize; - for (i = 0; i < SLICE_NUM_LOW; i++) - if (((lpsizes >> (i * 4)) & 0xf) == old_psize) - lpsizes = (lpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - - hpsizes = mm->context.high_slices_psize; - for (i = 0; i < SLICE_NUM_HIGH; i++) - if (((hpsizes >> (i * 4)) & 0xf) == old_psize) - hpsizes = (hpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - - mm->context.low_slices_psize = lpsizes; - mm->context.high_slices_psize = hpsizes; - - slice_dbg(" lsps=%lx, hsps=%lx\n", - mm->context.low_slices_psize, - mm->context.high_slices_psize); - - bail: - spin_unlock_irqrestore(&slice_convert_lock, flags); -} - -/* - * is_hugepage_only_range() is used by generic code to verify wether - * a normal mmap mapping (non hugetlbfs) is valid on a given area. - * - * until the generic code provides a more generic hook and/or starts - * calling arch get_unmapped_area for MAP_FIXED (which our implementation - * here knows how to deal with), we hijack it to keep standard mappings - * away from us. - * - * because of that generic code limitation, MAP_FIXED mapping cannot - * "convert" back a slice with no VMAs to the standard page size, only - * get_unmapped_area() can. It would be possible to fix it here but I - * prefer working on fixing the generic code instead. - * - * WARNING: This will not work if hugetlbfs isn't enabled since the - * generic code will redefine that function as 0 in that. This is ok - * for now as we only use slices with hugetlbfs enabled. This should - * be fixed as the generic code gets fixed. - */ -int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, - unsigned long len) -{ - struct slice_mask mask, available; - - mask = slice_range_to_mask(addr, len); - available = slice_mask_for_size(mm, mm->context.user_psize); - -#if 0 /* too verbose */ - slice_dbg("is_hugepage_only_range(mm=%p, addr=%lx, len=%lx)\n", - mm, addr, len); - slice_print_mask(" mask", mask); - slice_print_mask(" available", available); -#endif - return !slice_check_fit(mask, available); -} - diff --git a/trunk/arch/powerpc/mm/tlb_32.c b/trunk/arch/powerpc/mm/tlb_32.c index 6a69417cbc0e..925ff70be8ba 100644 --- a/trunk/arch/powerpc/mm/tlb_32.c +++ b/trunk/arch/powerpc/mm/tlb_32.c @@ -111,7 +111,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start, if (start >= end) return; end = (end - 1) | ~PAGE_MASK; - pmd = pmd_offset(pud_offset(pgd_offset(mm, start), start), start); + pmd = pmd_offset(pgd_offset(mm, start), start); for (;;) { pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1; if (pmd_end > end) @@ -169,7 +169,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) return; } mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pud_offset(pgd_offset(mm, vmaddr), vmaddr), vmaddr); + pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); if (!pmd_none(*pmd)) flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; diff --git a/trunk/arch/powerpc/mm/tlb_64.c b/trunk/arch/powerpc/mm/tlb_64.c index 2bfc4d7e1aa2..fd8d08c325eb 100644 --- a/trunk/arch/powerpc/mm/tlb_64.c +++ b/trunk/arch/powerpc/mm/tlb_64.c @@ -143,22 +143,16 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, */ addr &= PAGE_MASK; - /* Get page size (maybe move back to caller). - * - * NOTE: when using special 64K mappings in 4K environment like - * for SPEs, we obtain the page size from the slice, which thus - * must still exist (and thus the VMA not reused) at the time - * of this call - */ + /* Get page size (maybe move back to caller) */ if (huge) { #ifdef CONFIG_HUGETLB_PAGE psize = mmu_huge_psize; #else BUG(); - psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */ + psize = pte_pagesize_index(pte); /* shutup gcc */ #endif } else - psize = pte_pagesize_index(mm, addr, pte); + psize = pte_pagesize_index(pte); /* Build full vaddr */ if (!is_kernel_addr(addr)) { diff --git a/trunk/arch/powerpc/oprofile/op_model_cell.c b/trunk/arch/powerpc/oprofile/op_model_cell.c index c29293befba9..626b29f38304 100644 --- a/trunk/arch/powerpc/oprofile/op_model_cell.c +++ b/trunk/arch/powerpc/oprofile/op_model_cell.c @@ -747,7 +747,7 @@ cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) * counter value etc.) are not copied to the actual registers * until the performance monitor is enabled. In order to get * this to work as desired, the permormance monitor needs to - * be disabled while writing to the latches. This is a + * be disabled while writting to the latches. This is a * HW design issue. */ cbe_enable_pm(cpu); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 96970ac887ee..32e9e9492841 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c @@ -40,9 +40,7 @@ unsigned long isa_mem_base = 0; */ static void __init mpc8313_rdb_setup_arch(void) { -#ifdef CONFIG_PCI struct device_node *np; -#endif if (ppc_md.progress) ppc_md.progress("mpc8313_rdb_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 3db68b73fc32..b0b22bb29de7 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -44,9 +44,7 @@ unsigned long isa_mem_base = 0; */ static void __init mpc832x_rdb_setup_arch(void) { -#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE) struct device_node *np; -#endif if (ppc_md.progress) ppc_md.progress("mpc832x_rdb_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c index 40a01947d684..3c009f6d4a4f 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -50,9 +50,7 @@ unsigned long isa_mem_base = 0; */ static void __init mpc834x_itx_setup_arch(void) { -#ifdef CONFIG_PCI struct device_node *np; -#endif if (ppc_md.progress) ppc_md.progress("mpc834x_itx_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c index 10394b2d7e7a..8aa9a93e2aa2 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -120,9 +120,7 @@ static int mpc834x_usb_cfg(void) */ static void __init mpc834x_mds_setup_arch(void) { -#ifdef CONFIG_PCI struct device_node *np; -#endif if (ppc_md.progress) ppc_md.progress("mpc834x_mds_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 1051702c8d4f..90877565caa3 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -168,7 +168,7 @@ static void __devinit quirk_uli1575(struct pci_dev *dev) { unsigned short temp; struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned char irq2pin[16], c; + unsigned char irq2pin[16]; unsigned long pirq_map_word = 0; u32 irq; int i; @@ -288,11 +288,6 @@ static void __devinit quirk_uli1575(struct pci_dev *dev) outb(0x1e, 0x4d1); #undef ULI1575_SET_DEV_IRQ - - /* Disable the HD interface and enable the AC97 interface. */ - pci_read_config_byte(dev, 0xb8, &c); - c &= 0x7f; - pci_write_config_byte(dev, 0xb8, c); } static void __devinit quirk_uli5288(struct pci_dev *dev) diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/trunk/arch/powerpc/platforms/86xx/mpc86xx_smp.c index ba55b0ff0f74..7ef0c6854799 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx_smp.c +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -15,8 +15,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c index cf0e7bc8c2e7..a35315af5c53 100644 --- a/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -1,4 +1,4 @@ -/*arch/powerpc/platforms/8xx/mpc86xads_setup.c +/*arch/ppc/platforms/mpc86xads-setup.c * * Platform setup for the Freescale mpc86xads board * diff --git a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c36e475d93dc..a57b57785acd 100644 --- a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -1,4 +1,4 @@ -/*arch/powerpc/platforms/8xx/mpc885ads_setup.c +/*arch/ppc/platforms/mpc885ads-setup.c * * Platform setup for the Freescale mpc885ads board * diff --git a/trunk/arch/powerpc/platforms/cell/Kconfig b/trunk/arch/powerpc/platforms/cell/Kconfig index 9b2b386ccf48..82551770917c 100644 --- a/trunk/arch/powerpc/platforms/cell/Kconfig +++ b/trunk/arch/powerpc/platforms/cell/Kconfig @@ -35,21 +35,6 @@ config SPU_FS Units on machines implementing the Broadband Processor Architecture. -config SPU_FS_64K_LS - bool "Use 64K pages to map SPE local store" - # we depend on PPC_MM_SLICES for now rather than selecting - # it because we depend on hugetlbfs hooks being present. We - # will fix that when the generic code has been improved to - # not require hijacking hugetlbfs hooks. - depends on SPU_FS && PPC_MM_SLICES && !PPC_64K_PAGES - default y - select PPC_HAS_HASH_64K - help - This option causes SPE local stores to be mapped in process - address spaces using 64K pages while the rest of the kernel - uses 4K pages. This can improve performances of applications - using multiple SPEs by lowering the TLB pressure on them. - config SPU_BASE bool default n diff --git a/trunk/arch/powerpc/platforms/cell/io-workarounds.c b/trunk/arch/powerpc/platforms/cell/io-workarounds.c index 7fb92f23f380..d68d920eb2c4 100644 --- a/trunk/arch/powerpc/platforms/cell/io-workarounds.c +++ b/trunk/arch/powerpc/platforms/cell/io-workarounds.c @@ -74,7 +74,7 @@ static void spider_io_flush(const volatile void __iomem *addr) /* Fast path if we have a non-0 token, it indicates which bus we * are on. * - * If the token is 0, that means either that the ioremap was done + * If the token is 0, that means either the the ioremap was done * before we initialized this layer, or it's a PIO operation. We * fallback to a low path in this case. Hopefully, internal devices * which are ioremap'ed early should use in_XX/out_XX functions diff --git a/trunk/arch/powerpc/platforms/cell/pervasive.c b/trunk/arch/powerpc/platforms/cell/pervasive.c index 812bf563ed65..8c20f0fb8651 100644 --- a/trunk/arch/powerpc/platforms/cell/pervasive.c +++ b/trunk/arch/powerpc/platforms/cell/pervasive.c @@ -43,10 +43,12 @@ static void cbe_power_save(void) unsigned long ctrl, thread_switch_control; /* - * We need to hard disable interrupts, the local_irq_enable() done by - * our caller upon return will hard re-enable. + * We need to hard disable interrupts, but we also need to mark them + * hard disabled in the PACA so that the local_irq_enable() done by + * our caller upon return propertly hard enables. */ hard_irq_disable(); + get_paca()->hard_enabled = 0; ctrl = mfspr(SPRN_CTRLF); diff --git a/trunk/arch/powerpc/platforms/cell/spu_base.c b/trunk/arch/powerpc/platforms/cell/spu_base.c index a7f5a7653c62..fec51525252e 100644 --- a/trunk/arch/powerpc/platforms/cell/spu_base.c +++ b/trunk/arch/powerpc/platforms/cell/spu_base.c @@ -144,11 +144,12 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) switch(REGION_ID(ea)) { case USER_REGION_ID: -#ifdef CONFIG_PPC_MM_SLICES - psize = get_slice_psize(mm, ea); -#else - psize = mm->context.user_psize; +#ifdef CONFIG_HUGETLB_PAGE + if (in_hugepage_area(mm->context, ea)) + psize = mmu_huge_psize; + else #endif + psize = mm->context.user_psize; vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER; break; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/Makefile b/trunk/arch/powerpc/platforms/cell/spufs/Makefile index 328afcf89503..2cd89c11af5a 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/Makefile +++ b/trunk/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,4 +1,4 @@ -obj-y += switch.o fault.o lscsa_alloc.o +obj-y += switch.o fault.o obj-$(CONFIG_SPU_FS) += spufs.o spufs-y += inode.o file.o context.o syscalls.o coredump.o diff --git a/trunk/arch/powerpc/platforms/cell/spufs/context.c b/trunk/arch/powerpc/platforms/cell/spufs/context.c index 8654749e317b..a87d9ca3dba2 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/context.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/context.c @@ -36,8 +36,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) /* Binding to physical processor deferred * until spu_activate(). */ - if (spu_init_csa(&ctx->csa)) + spu_init_csa(&ctx->csa); + if (!ctx->csa.lscsa) { goto out_free; + } spin_lock_init(&ctx->mmio_lock); spin_lock_init(&ctx->mapping_lock); kref_init(&ctx->kref); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/file.c b/trunk/arch/powerpc/platforms/cell/spufs/file.c index 45614c73c784..d010b2464a98 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/file.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/file.c @@ -118,32 +118,14 @@ spufs_mem_write(struct file *file, const char __user *buffer, static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, unsigned long address) { - struct spu_context *ctx = vma->vm_file->private_data; - unsigned long pfn, offset, addr0 = address; -#ifdef CONFIG_SPU_FS_64K_LS - struct spu_state *csa = &ctx->csa; - int psize; - - /* Check what page size we are using */ - psize = get_slice_psize(vma->vm_mm, address); - - /* Some sanity checking */ - BUG_ON(csa->use_big_pages != (psize == MMU_PAGE_64K)); - - /* Wow, 64K, cool, we need to align the address though */ - if (csa->use_big_pages) { - BUG_ON(vma->vm_start & 0xffff); - address &= ~0xfffful; - } -#endif /* CONFIG_SPU_FS_64K_LS */ + struct spu_context *ctx = vma->vm_file->private_data; + unsigned long pfn, offset = address - vma->vm_start; + + offset += vma->vm_pgoff << PAGE_SHIFT; - offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); if (offset >= LS_SIZE) return NOPFN_SIGBUS; - pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n", - addr0, address, offset); - spu_acquire(ctx); if (ctx->state == SPU_STATE_SAVED) { @@ -167,24 +149,9 @@ static struct vm_operations_struct spufs_mem_mmap_vmops = { .nopfn = spufs_mem_mmap_nopfn, }; -static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) -{ -#ifdef CONFIG_SPU_FS_64K_LS - struct spu_context *ctx = file->private_data; - struct spu_state *csa = &ctx->csa; - - /* Sanity check VMA alignment */ - if (csa->use_big_pages) { - pr_debug("spufs_mem_mmap 64K, start=0x%lx, end=0x%lx," - " pgoff=0x%lx\n", vma->vm_start, vma->vm_end, - vma->vm_pgoff); - if (vma->vm_start & 0xffff) - return -EINVAL; - if (vma->vm_pgoff & 0xf) - return -EINVAL; - } -#endif /* CONFIG_SPU_FS_64K_LS */ - +static int +spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) +{ if (!(vma->vm_flags & VM_SHARED)) return -EINVAL; @@ -196,34 +163,13 @@ static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -#ifdef CONFIG_SPU_FS_64K_LS -unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) -{ - struct spu_context *ctx = file->private_data; - struct spu_state *csa = &ctx->csa; - - /* If not using big pages, fallback to normal MM g_u_a */ - if (!csa->use_big_pages) - return current->mm->get_unmapped_area(file, addr, len, - pgoff, flags); - - /* Else, try to obtain a 64K pages slice */ - return slice_get_unmapped_area(addr, len, flags, - MMU_PAGE_64K, 1, 0); -} -#endif /* CONFIG_SPU_FS_64K_LS */ - static const struct file_operations spufs_mem_fops = { - .open = spufs_mem_open, - .read = spufs_mem_read, - .write = spufs_mem_write, - .llseek = generic_file_llseek, - .mmap = spufs_mem_mmap, -#ifdef CONFIG_SPU_FS_64K_LS - .get_unmapped_area = spufs_get_unmapped_area, -#endif + .open = spufs_mem_open, + .release = spufs_mem_release, + .read = spufs_mem_read, + .write = spufs_mem_write, + .llseek = generic_file_llseek, + .mmap = spufs_mem_mmap, }; static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, diff --git a/trunk/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/trunk/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c deleted file mode 100644 index f4b3c052dabf..000000000000 --- a/trunk/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * SPU local store allocation routines - * - * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#undef DEBUG - -#include -#include -#include - -#include -#include -#include - -static int spu_alloc_lscsa_std(struct spu_state *csa) -{ - struct spu_lscsa *lscsa; - unsigned char *p; - - lscsa = vmalloc(sizeof(struct spu_lscsa)); - if (!lscsa) - return -ENOMEM; - memset(lscsa, 0, sizeof(struct spu_lscsa)); - csa->lscsa = lscsa; - - /* Set LS pages reserved to allow for user-space mapping. */ - for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) - SetPageReserved(vmalloc_to_page(p)); - - return 0; -} - -static void spu_free_lscsa_std(struct spu_state *csa) -{ - /* Clear reserved bit before vfree. */ - unsigned char *p; - - if (csa->lscsa == NULL) - return; - - for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) - ClearPageReserved(vmalloc_to_page(p)); - - vfree(csa->lscsa); -} - -#ifdef CONFIG_SPU_FS_64K_LS - -#define SPU_64K_PAGE_SHIFT 16 -#define SPU_64K_PAGE_ORDER (SPU_64K_PAGE_SHIFT - PAGE_SHIFT) -#define SPU_64K_PAGE_COUNT (1ul << SPU_64K_PAGE_ORDER) - -int spu_alloc_lscsa(struct spu_state *csa) -{ - struct page **pgarray; - unsigned char *p; - int i, j, n_4k; - - /* Check availability of 64K pages */ - if (mmu_psize_defs[MMU_PAGE_64K].shift == 0) - goto fail; - - csa->use_big_pages = 1; - - pr_debug("spu_alloc_lscsa(csa=0x%p), trying to allocate 64K pages\n", - csa); - - /* First try to allocate our 64K pages. We need 5 of them - * with the current implementation. In the future, we should try - * to separate the lscsa with the actual local store image, thus - * allowing us to require only 4 64K pages per context - */ - for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) { - /* XXX This is likely to fail, we should use a special pool - * similiar to what hugetlbfs does. - */ - csa->lscsa_pages[i] = alloc_pages(GFP_KERNEL, - SPU_64K_PAGE_ORDER); - if (csa->lscsa_pages[i] == NULL) - goto fail; - } - - pr_debug(" success ! creating vmap...\n"); - - /* Now we need to create a vmalloc mapping of these for the kernel - * and SPU context switch code to use. Currently, we stick to a - * normal kernel vmalloc mapping, which in our case will be 4K - */ - n_4k = SPU_64K_PAGE_COUNT * SPU_LSCSA_NUM_BIG_PAGES; - pgarray = kmalloc(sizeof(struct page *) * n_4k, GFP_KERNEL); - if (pgarray == NULL) - goto fail; - for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) - for (j = 0; j < SPU_64K_PAGE_COUNT; j++) - /* We assume all the struct page's are contiguous - * which should be hopefully the case for an order 4 - * allocation.. - */ - pgarray[i * SPU_64K_PAGE_COUNT + j] = - csa->lscsa_pages[i] + j; - csa->lscsa = vmap(pgarray, n_4k, VM_USERMAP, PAGE_KERNEL); - kfree(pgarray); - if (csa->lscsa == NULL) - goto fail; - - memset(csa->lscsa, 0, sizeof(struct spu_lscsa)); - - /* Set LS pages reserved to allow for user-space mapping. - * - * XXX isn't that a bit obsolete ? I think we should just - * make sure the page count is high enough. Anyway, won't harm - * for now - */ - for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) - SetPageReserved(vmalloc_to_page(p)); - - pr_debug(" all good !\n"); - - return 0; -fail: - pr_debug("spufs: failed to allocate lscsa 64K pages, falling back\n"); - spu_free_lscsa(csa); - return spu_alloc_lscsa_std(csa); -} - -void spu_free_lscsa(struct spu_state *csa) -{ - unsigned char *p; - int i; - - if (!csa->use_big_pages) { - spu_free_lscsa_std(csa); - return; - } - csa->use_big_pages = 0; - - if (csa->lscsa == NULL) - goto free_pages; - - for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) - ClearPageReserved(vmalloc_to_page(p)); - - vunmap(csa->lscsa); - csa->lscsa = NULL; - - free_pages: - - for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) - if (csa->lscsa_pages[i]) - __free_pages(csa->lscsa_pages[i], SPU_64K_PAGE_ORDER); -} - -#else /* CONFIG_SPU_FS_64K_LS */ - -int spu_alloc_lscsa(struct spu_state *csa) -{ - return spu_alloc_lscsa_std(csa); -} - -void spu_free_lscsa(struct spu_state *csa) -{ - spu_free_lscsa_std(csa); -} - -#endif /* !defined(CONFIG_SPU_FS_64K_LS) */ diff --git a/trunk/arch/powerpc/platforms/cell/spufs/switch.c b/trunk/arch/powerpc/platforms/cell/spufs/switch.c index 71a0b41adb8c..29dc59cefc38 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/switch.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/switch.c @@ -2188,30 +2188,40 @@ static void init_priv2(struct spu_state *csa) * as it is by far the largest of the context save regions, * and may need to be pinned or otherwise specially aligned. */ -int spu_init_csa(struct spu_state *csa) +void spu_init_csa(struct spu_state *csa) { - int rc; + struct spu_lscsa *lscsa; + unsigned char *p; if (!csa) - return -EINVAL; + return; memset(csa, 0, sizeof(struct spu_state)); - rc = spu_alloc_lscsa(csa); - if (rc) - return rc; + lscsa = vmalloc(sizeof(struct spu_lscsa)); + if (!lscsa) + return; + memset(lscsa, 0, sizeof(struct spu_lscsa)); + csa->lscsa = lscsa; spin_lock_init(&csa->register_lock); + /* Set LS pages reserved to allow for user-space mapping. */ + for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) + SetPageReserved(vmalloc_to_page(p)); + init_prob(csa); init_priv1(csa); init_priv2(csa); - - return 0; } EXPORT_SYMBOL_GPL(spu_init_csa); void spu_fini_csa(struct spu_state *csa) { - spu_free_lscsa(csa); + /* Clear reserved bit before vfree. */ + unsigned char *p; + for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) + ClearPageReserved(vmalloc_to_page(p)); + + vfree(csa->lscsa); } EXPORT_SYMBOL_GPL(spu_fini_csa); diff --git a/trunk/arch/powerpc/platforms/celleb/pci.c b/trunk/arch/powerpc/platforms/celleb/pci.c index e9ac19c4bba4..d1adf34cd5e8 100644 --- a/trunk/arch/powerpc/platforms/celleb/pci.c +++ b/trunk/arch/powerpc/platforms/celleb/pci.c @@ -457,7 +457,6 @@ int __devinit celleb_setup_phb(struct pci_controller *phb) pr_debug("PCI: celleb_setup_phb() %s\n", name); phb_set_bus_ranges(dev, phb); - phb->buid = 1; if (strcmp(name, "epci") == 0) { phb->ops = &celleb_epci_ops; diff --git a/trunk/arch/powerpc/platforms/celleb/scc_epci.c b/trunk/arch/powerpc/platforms/celleb/scc_epci.c index c4b011094bd6..fb23d53eb09c 100644 --- a/trunk/arch/powerpc/platforms/celleb/scc_epci.c +++ b/trunk/arch/powerpc/platforms/celleb/scc_epci.c @@ -133,13 +133,13 @@ static int celleb_epci_check_abort(struct pci_controller *hose, } static volatile void __iomem *celleb_epci_make_config_addr( - struct pci_bus *bus, struct pci_controller *hose, unsigned int devfn, int where) { volatile void __iomem *addr; + struct pci_bus *bus = hose->bus; - if (bus != hose->bus) + if (bus->self) addr = celleb_epci_get_epci_cfg(hose) + (((bus->number & 0xff) << 16) | ((devfn & 0xff) << 8) @@ -193,7 +193,7 @@ static int celleb_epci_read_config(struct pci_bus *bus, } else { clear_and_disable_master_abort_interrupt(hose); - addr = celleb_epci_make_config_addr(bus, hose, devfn, where); + addr = celleb_epci_make_config_addr(hose, devfn, where); switch (size) { case 1: @@ -257,7 +257,7 @@ static int celleb_epci_write_config(struct pci_bus *bus, } else { clear_and_disable_master_abort_interrupt(hose); - addr = celleb_epci_make_config_addr(bus, hose, devfn, where); + addr = celleb_epci_make_config_addr(hose, devfn, where); switch (size) { case 1: diff --git a/trunk/arch/powerpc/platforms/celleb/setup.c b/trunk/arch/powerpc/platforms/celleb/setup.c index 5e9f7f163571..596ab2a788d4 100644 --- a/trunk/arch/powerpc/platforms/celleb/setup.c +++ b/trunk/arch/powerpc/platforms/celleb/setup.c @@ -80,7 +80,7 @@ static int celleb_machine_type_hack(char *ptr) return 0; } -__setup("celleb_machine_type_hack=", celleb_machine_type_hack); +__setup("celleb_machine_type_hack", celleb_machine_type_hack); static void celleb_progress(char *s, unsigned short hex) { diff --git a/trunk/arch/powerpc/platforms/iseries/Kconfig b/trunk/arch/powerpc/platforms/iseries/Kconfig index 761d9e971fc4..46c3a8e7c3a8 100644 --- a/trunk/arch/powerpc/platforms/iseries/Kconfig +++ b/trunk/arch/powerpc/platforms/iseries/Kconfig @@ -7,9 +7,7 @@ menu "iSeries device drivers" depends on PPC_ISERIES config VIOCONS - bool "iSeries Virtual Console Support (Obsolete)" - depends on !HVC_ISERIES - default n + tristate "iSeries Virtual Console Support (Obsolete)" help This is the old virtual console driver for legacy iSeries. You should use the iSeries Hypervisor Virtual Console diff --git a/trunk/arch/powerpc/platforms/pseries/eeh.c b/trunk/arch/powerpc/platforms/pseries/eeh.c index 5f3e6d8659fe..63e23062e982 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh.c @@ -76,7 +76,7 @@ */ #define EEH_MAX_FAILS 2100000 -/* Time to wait for a PCI slot to report status, in milliseconds */ +/* Time to wait for a PCI slot to retport status, in milliseconds */ #define PCI_BUS_RESET_WAIT_MSEC (60*1000) /* RTAS tokens */ @@ -95,21 +95,11 @@ EXPORT_SYMBOL(eeh_subsystem_enabled); /* Lock to avoid races due to multiple reports of an error */ static DEFINE_SPINLOCK(confirm_error_lock); -/* Buffer for reporting slot-error-detail rtas calls. Its here - * in BSS, and not dynamically alloced, so that it ends up in - * RMO where RTAS can access it. - */ +/* Buffer for reporting slot-error-detail rtas calls */ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; static DEFINE_SPINLOCK(slot_errbuf_lock); static int eeh_error_buf_size; -/* Buffer for reporting pci register dumps. Its here in BSS, and - * not dynamically alloced, so that it ends up in RMO where RTAS - * can access it. - */ -#define EEH_PCI_REGS_LOG_LEN 4096 -static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; - /* System monitoring statistics */ static unsigned long no_device; static unsigned long no_dn; @@ -125,8 +115,7 @@ static unsigned long slot_resets; /* --------------------------------------------------------------- */ /* Below lies the EEH event infrastructure */ -static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, - char *driver_log, size_t loglen) +void eeh_slot_error_detail (struct pci_dn *pdn, int severity) { int config_addr; unsigned long flags; @@ -144,8 +133,7 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, rc = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr, BUID_HI(pdn->phb->buid), - BUID_LO(pdn->phb->buid), - virt_to_phys(driver_log), loglen, + BUID_LO(pdn->phb->buid), NULL, 0, virt_to_phys(slot_errbuf), eeh_error_buf_size, severity); @@ -155,84 +143,6 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, spin_unlock_irqrestore(&slot_errbuf_lock, flags); } -/** - * gather_pci_data - copy assorted PCI config space registers to buff - * @pdn: device to report data for - * @buf: point to buffer in which to log - * @len: amount of room in buffer - * - * This routine captures assorted PCI configuration space data, - * and puts them into a buffer for RTAS error logging. - */ -static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) -{ - u32 cfg; - int cap, i; - int n = 0; - - n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name); - printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name); - - rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); - n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); - printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); - - rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); - n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); - printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); - - /* Dump out the PCI-X command and status regs */ - cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); - if (cap) { - rtas_read_config(pdn, cap, 4, &cfg); - n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); - printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); - - rtas_read_config(pdn, cap+4, 4, &cfg); - n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); - printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); - } - - /* If PCI-E capable, dump PCI-E cap 10, and the AER */ - cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP); - if (cap) { - n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); - printk(KERN_WARNING - "EEH: PCI-E capabilities and status follow:\n"); - - for (i=0; i<=8; i++) { - rtas_read_config(pdn, cap+4*i, 4, &cfg); - n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); - printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); - } - - cap = pci_find_ext_capability(pdn->pcidev,PCI_EXT_CAP_ID_ERR); - if (cap) { - n += scnprintf(buf+n, len-n, "pci-e AER:\n"); - printk(KERN_WARNING - "EEH: PCI-E AER capability register set follows:\n"); - - for (i=0; i<14; i++) { - rtas_read_config(pdn, cap+4*i, 4, &cfg); - n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); - printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); - } - } - } - return n; -} - -void eeh_slot_error_detail(struct pci_dn *pdn, int severity) -{ - size_t loglen = 0; - pci_regs_buf[0] = 0; - - rtas_pci_enable(pdn, EEH_THAW_MMIO); - loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); - - rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); -} - /** * read_slot_reset_state - Read the reset state of a device node's slot * @dn: device node to read diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c index 161a5844ab6c..3170e003f76a 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c @@ -361,12 +361,11 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) goto hard_fail; } + eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING - "EEH: This PCI device has failed %d times in the last hour:\n", - frozen_pdn->eeh_freeze_count); - printk(KERN_WARNING - "EEH: location=%s driver=%s pci addr=%s\n", - location, drv_str, pci_str); + "EEH: This PCI device has failed %d times since last reboot: " + "location=%s driver=%s pci addr=%s\n", + frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -376,12 +375,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) */ pci_walk_bus(frozen_bus, eeh_report_error, &result); - /* Since rtas may enable MMIO when posting the error log, - * don't post the error log until after all dev drivers - * have been informed. - */ - eeh_slot_error_detail(frozen_pdn, EEH_LOG_TEMP_FAILURE); - /* If all device drivers were EEH-unaware, then shut * down all of the device drivers, and hope they * go down willingly, without panicing the system. @@ -471,7 +464,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) location, drv_str, pci_str); perm_error: - eeh_slot_error_detail(frozen_pdn, EEH_LOG_PERM_FAILURE); + eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); /* Notify all devices that they're about to go down. */ pci_walk_bus(frozen_bus, eeh_report_failure, NULL); diff --git a/trunk/arch/powerpc/platforms/pseries/iommu.c b/trunk/arch/powerpc/platforms/pseries/iommu.c index be17d2395072..eec684a8e44e 100644 --- a/trunk/arch/powerpc/platforms/pseries/iommu.c +++ b/trunk/arch/powerpc/platforms/pseries/iommu.c @@ -520,6 +520,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; return; } + DBG(" found DMA window, table: %p\n", pci->iommu_table); pci = PCI_DN(pdn); if (!pci->iommu_table) { @@ -533,8 +534,6 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) pci->iommu_table = iommu_init_table(tbl, pci->phb->node); DBG(" created table: %p\n", pci->iommu_table); - } else { - DBG(" found DMA window, table: %p\n", pci->iommu_table); } dev->dev.archdata.dma_data = pci->iommu_table; diff --git a/trunk/arch/powerpc/platforms/pseries/kexec.c b/trunk/arch/powerpc/platforms/pseries/kexec.c index 412a5e7aff2d..af2685607458 100644 --- a/trunk/arch/powerpc/platforms/pseries/kexec.c +++ b/trunk/arch/powerpc/platforms/pseries/kexec.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "pseries.h" #include "xics.h" diff --git a/trunk/arch/powerpc/sysdev/commproc.c b/trunk/arch/powerpc/sysdev/commproc.c index 4f67b89ba1d0..9b4fafd9a840 100644 --- a/trunk/arch/powerpc/sysdev/commproc.c +++ b/trunk/arch/powerpc/sysdev/commproc.c @@ -330,7 +330,7 @@ void m8xx_cpm_dpinit(void) * with the processor and the microcode patches applied / activated. * But the following should be at least safe. */ - rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); + rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); } /* @@ -338,9 +338,9 @@ void m8xx_cpm_dpinit(void) * This function returns an offset into the DPRAM area. * Use cpm_dpram_addr() to get the virtual address of the area. */ -unsigned long cpm_dpalloc(uint size, uint align) +uint cpm_dpalloc(uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); @@ -352,30 +352,30 @@ unsigned long cpm_dpalloc(uint size, uint align) } EXPORT_SYMBOL(cpm_dpalloc); -int cpm_dpfree(unsigned long offset) +int cpm_dpfree(uint offset) { int ret; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); - ret = rh_free(&cpm_dpmem_info, offset); + ret = rh_free(&cpm_dpmem_info, (void *)offset); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); return ret; } EXPORT_SYMBOL(cpm_dpfree); -unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align) +uint cpm_dpalloc_fixed(uint offset, uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); cpm_dpmem_info.alignment = align; - start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc"); + start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc_fixed); @@ -385,7 +385,7 @@ void cpm_dpdump(void) } EXPORT_SYMBOL(cpm_dpdump); -void *cpm_dpram_addr(unsigned long offset) +void *cpm_dpram_addr(uint offset) { return (void *)(dpram_vbase + offset); } diff --git a/trunk/arch/powerpc/sysdev/cpm2_common.c b/trunk/arch/powerpc/sysdev/cpm2_common.c index 924412974795..ec265995d5d8 100644 --- a/trunk/arch/powerpc/sysdev/cpm2_common.c +++ b/trunk/arch/powerpc/sysdev/cpm2_common.c @@ -248,14 +248,15 @@ static void cpm2_dpinit(void) * varies with the processor and the microcode patches activated. * But the following should be at least safe. */ - rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); + rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, + CPM_DATAONLY_SIZE); } /* This function returns an index into the DPRAM area. */ -unsigned long cpm_dpalloc(uint size, uint align) +uint cpm_dpalloc(uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); @@ -267,13 +268,13 @@ unsigned long cpm_dpalloc(uint size, uint align) } EXPORT_SYMBOL(cpm_dpalloc); -int cpm_dpfree(unsigned long offset) +int cpm_dpfree(uint offset) { int ret; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); - ret = rh_free(&cpm_dpmem_info, offset); + ret = rh_free(&cpm_dpmem_info, (void *)offset); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); return ret; @@ -281,17 +282,17 @@ int cpm_dpfree(unsigned long offset) EXPORT_SYMBOL(cpm_dpfree); /* not sure if this is ever needed */ -unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align) +uint cpm_dpalloc_fixed(uint offset, uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); cpm_dpmem_info.alignment = align; - start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc"); + start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc_fixed); @@ -301,7 +302,7 @@ void cpm_dpdump(void) } EXPORT_SYMBOL(cpm_dpdump); -void *cpm_dpram_addr(unsigned long offset) +void *cpm_dpram_addr(uint offset) { return (void *)(im_dprambase + offset); } diff --git a/trunk/arch/powerpc/sysdev/fsl_soc.c b/trunk/arch/powerpc/sysdev/fsl_soc.c index cad175724359..8a123c71449f 100644 --- a/trunk/arch/powerpc/sysdev/fsl_soc.c +++ b/trunk/arch/powerpc/sysdev/fsl_soc.c @@ -907,7 +907,7 @@ static int __init fs_enet_of_init(void) struct fs_platform_info fs_enet_data; const unsigned int *id; const unsigned int *phy_addr; - const void *mac_addr; + void *mac_addr; const phandle *ph; const char *model; diff --git a/trunk/arch/powerpc/sysdev/qe_lib/qe.c b/trunk/arch/powerpc/sysdev/qe_lib/qe.c index 90f87408b5d5..7f4c07543961 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/qe.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/qe.c @@ -244,7 +244,7 @@ EXPORT_SYMBOL(qe_put_snum); static int qe_sdma_init(void) { struct sdma *sdma = &qe_immr->sdma; - unsigned long sdma_buf_offset; + u32 sdma_buf_offset; if (!sdma) return -ENODEV; @@ -252,10 +252,10 @@ static int qe_sdma_init(void) /* allocate 2 internal temporary buffers (512 bytes size each) for * the SDMA */ sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); - if (IS_ERR_VALUE(sdma_buf_offset)) + if (IS_MURAM_ERR(sdma_buf_offset)) return -ENOMEM; - out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK); + out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK); out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | (0x1 << QE_SDMR_CEN_SHIFT))); @@ -291,32 +291,33 @@ static void qe_muram_init(void) if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) { address = *of_get_address(np, 0, &size, &flags); of_node_put(np); - rh_attach_region(&qe_muram_info, address, (int) size); + rh_attach_region(&qe_muram_info, + (void *)address, (int)size); } } /* This function returns an index into the MURAM area. */ -unsigned long qe_muram_alloc(int size, int align) +u32 qe_muram_alloc(u32 size, u32 align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&qe_muram_lock, flags); start = rh_alloc_align(&qe_muram_info, size, align, "QE"); spin_unlock_irqrestore(&qe_muram_lock, flags); - return start; + return (u32) start; } EXPORT_SYMBOL(qe_muram_alloc); -int qe_muram_free(unsigned long offset) +int qe_muram_free(u32 offset) { int ret; unsigned long flags; spin_lock_irqsave(&qe_muram_lock, flags); - ret = rh_free(&qe_muram_info, offset); + ret = rh_free(&qe_muram_info, (void *)offset); spin_unlock_irqrestore(&qe_muram_lock, flags); return ret; @@ -324,16 +325,16 @@ int qe_muram_free(unsigned long offset) EXPORT_SYMBOL(qe_muram_free); /* not sure if this is ever needed */ -unsigned long qe_muram_alloc_fixed(unsigned long offset, int size) +u32 qe_muram_alloc_fixed(u32 offset, u32 size) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&qe_muram_lock, flags); - start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc"); + start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc"); spin_unlock_irqrestore(&qe_muram_lock, flags); - return start; + return (u32) start; } EXPORT_SYMBOL(qe_muram_alloc_fixed); @@ -343,7 +344,7 @@ void qe_muram_dump(void) } EXPORT_SYMBOL(qe_muram_dump); -void *qe_muram_addr(unsigned long offset) +void *qe_muram_addr(u32 offset) { return (void *)&qe_immr->muram[offset]; } diff --git a/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 9143236853fc..66137bf2dfb0 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -269,7 +268,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* Allocate memory for Tx Virtual Fifo */ uccf->ucc_fast_tx_virtual_fifo_base_offset = qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); - if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) { + if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) { printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__); uccf->ucc_fast_tx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); @@ -281,7 +280,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc qe_muram_alloc(uf_info->urfs + UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); - if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) { + if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) { printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__); uccf->ucc_fast_rx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); diff --git a/trunk/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/trunk/arch/powerpc/sysdev/qe_lib/ucc_slow.c index 1f65c26ce63f..b930d686a4d1 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -176,7 +175,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* Get PRAM base */ uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM); - if (IS_ERR_VALUE(uccs->us_pram_offset)) { + if (IS_MURAM_ERR(uccs->us_pram_offset)) { printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__); ucc_slow_free(uccs); return -ENOMEM; @@ -211,7 +210,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->rx_base_offset = qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); - if (IS_ERR_VALUE(uccs->rx_base_offset)) { + if (IS_MURAM_ERR(uccs->rx_base_offset)) { printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__); uccs->rx_base_offset = 0; ucc_slow_free(uccs); @@ -221,7 +220,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->tx_base_offset = qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); - if (IS_ERR_VALUE(uccs->tx_base_offset)) { + if (IS_MURAM_ERR(uccs->tx_base_offset)) { printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__); uccs->tx_base_offset = 0; ucc_slow_free(uccs); diff --git a/trunk/arch/ppc/8xx_io/commproc.c b/trunk/arch/ppc/8xx_io/commproc.c index e2c6210f234b..7a8722beac12 100644 --- a/trunk/arch/ppc/8xx_io/commproc.c +++ b/trunk/arch/ppc/8xx_io/commproc.c @@ -402,7 +402,7 @@ void m8xx_cpm_dpinit(void) * with the processor and the microcode patches applied / activated. * But the following should be at least safe. */ - rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); + rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); } /* @@ -410,9 +410,9 @@ void m8xx_cpm_dpinit(void) * This function returns an offset into the DPRAM area. * Use cpm_dpram_addr() to get the virtual address of the area. */ -unsigned long cpm_dpalloc(uint size, uint align) +uint cpm_dpalloc(uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); @@ -420,34 +420,34 @@ unsigned long cpm_dpalloc(uint size, uint align) start = rh_alloc(&cpm_dpmem_info, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc); -int cpm_dpfree(unsigned long offset) +int cpm_dpfree(uint offset) { int ret; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); - ret = rh_free(&cpm_dpmem_info, offset); + ret = rh_free(&cpm_dpmem_info, (void *)offset); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); return ret; } EXPORT_SYMBOL(cpm_dpfree); -unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align) +uint cpm_dpalloc_fixed(uint offset, uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); cpm_dpmem_info.alignment = align; - start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc"); + start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc_fixed); @@ -457,7 +457,7 @@ void cpm_dpdump(void) } EXPORT_SYMBOL(cpm_dpdump); -void *cpm_dpram_addr(unsigned long offset) +void *cpm_dpram_addr(uint offset) { return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset; } diff --git a/trunk/arch/ppc/kernel/asm-offsets.c b/trunk/arch/ppc/kernel/asm-offsets.c index e8e94321b59e..c5850a272650 100644 --- a/trunk/arch/ppc/kernel/asm-offsets.c +++ b/trunk/arch/ppc/kernel/asm-offsets.c @@ -35,7 +35,7 @@ int main(void) { DEFINE(THREAD, offsetof(struct task_struct, thread)); - DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(MM, offsetof(struct task_struct, mm)); DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); diff --git a/trunk/arch/ppc/lib/Makefile b/trunk/arch/ppc/lib/Makefile index 095e661e79dd..422bef9bae7b 100644 --- a/trunk/arch/ppc/lib/Makefile +++ b/trunk/arch/ppc/lib/Makefile @@ -3,3 +3,6 @@ # obj-y := checksum.o string.o div64.o + +obj-$(CONFIG_8xx) += rheap.o +obj-$(CONFIG_CPM2) += rheap.o diff --git a/trunk/arch/ppc/lib/rheap.c b/trunk/arch/ppc/lib/rheap.c new file mode 100644 index 000000000000..d40700795a9c --- /dev/null +++ b/trunk/arch/ppc/lib/rheap.c @@ -0,0 +1,692 @@ +/* + * A Remote Heap. Remote means that we don't touch the memory that the + * heap points to. Normal heap implementations use the memory they manage + * to place their list. We cannot do that because the memory we manage may + * have special properties, for example it is uncachable or of different + * endianess. + * + * Author: Pantelis Antoniou + * + * 2004 (c) INTRACOM S.A. Greece. 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 + +/* + * Fixup a list_head, needed when copying lists. If the pointers fall + * between s and e, apply the delta. This assumes that + * sizeof(struct list_head *) == sizeof(unsigned long *). + */ +static inline void fixup(unsigned long s, unsigned long e, int d, + struct list_head *l) +{ + unsigned long *pp; + + pp = (unsigned long *)&l->next; + if (*pp >= s && *pp < e) + *pp += d; + + pp = (unsigned long *)&l->prev; + if (*pp >= s && *pp < e) + *pp += d; +} + +/* Grow the allocated blocks */ +static int grow(rh_info_t * info, int max_blocks) +{ + rh_block_t *block, *blk; + int i, new_blocks; + int delta; + unsigned long blks, blke; + + if (max_blocks <= info->max_blocks) + return -EINVAL; + + new_blocks = max_blocks - info->max_blocks; + + block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL); + if (block == NULL) + return -ENOMEM; + + if (info->max_blocks > 0) { + + /* copy old block area */ + memcpy(block, info->block, + sizeof(rh_block_t) * info->max_blocks); + + delta = (char *)block - (char *)info->block; + + /* and fixup list pointers */ + blks = (unsigned long)info->block; + blke = (unsigned long)(info->block + info->max_blocks); + + for (i = 0, blk = block; i < info->max_blocks; i++, blk++) + fixup(blks, blke, delta, &blk->list); + + fixup(blks, blke, delta, &info->empty_list); + fixup(blks, blke, delta, &info->free_list); + fixup(blks, blke, delta, &info->taken_list); + + /* free the old allocated memory */ + if ((info->flags & RHIF_STATIC_BLOCK) == 0) + kfree(info->block); + } + + info->block = block; + info->empty_slots += new_blocks; + info->max_blocks = max_blocks; + info->flags &= ~RHIF_STATIC_BLOCK; + + /* add all new blocks to the free list */ + for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++) + list_add(&blk->list, &info->empty_list); + + return 0; +} + +/* + * Assure at least the required amount of empty slots. If this function + * causes a grow in the block area then all pointers kept to the block + * area are invalid! + */ +static int assure_empty(rh_info_t * info, int slots) +{ + int max_blocks; + + /* This function is not meant to be used to grow uncontrollably */ + if (slots >= 4) + return -EINVAL; + + /* Enough space */ + if (info->empty_slots >= slots) + return 0; + + /* Next 16 sized block */ + max_blocks = ((info->max_blocks + slots) + 15) & ~15; + + return grow(info, max_blocks); +} + +static rh_block_t *get_slot(rh_info_t * info) +{ + rh_block_t *blk; + + /* If no more free slots, and failure to extend. */ + /* XXX: You should have called assure_empty before */ + if (info->empty_slots == 0) { + printk(KERN_ERR "rh: out of slots; crash is imminent.\n"); + return NULL; + } + + /* Get empty slot to use */ + blk = list_entry(info->empty_list.next, rh_block_t, list); + list_del_init(&blk->list); + info->empty_slots--; + + /* Initialize */ + blk->start = NULL; + blk->size = 0; + blk->owner = NULL; + + return blk; +} + +static inline void release_slot(rh_info_t * info, rh_block_t * blk) +{ + list_add(&blk->list, &info->empty_list); + info->empty_slots++; +} + +static void attach_free_block(rh_info_t * info, rh_block_t * blkn) +{ + rh_block_t *blk; + rh_block_t *before; + rh_block_t *after; + rh_block_t *next; + int size; + unsigned long s, e, bs, be; + struct list_head *l; + + /* We assume that they are aligned properly */ + size = blkn->size; + s = (unsigned long)blkn->start; + e = s + size; + + /* Find the blocks immediately before and after the given one + * (if any) */ + before = NULL; + after = NULL; + next = NULL; + + list_for_each(l, &info->free_list) { + blk = list_entry(l, rh_block_t, list); + + bs = (unsigned long)blk->start; + be = bs + blk->size; + + if (next == NULL && s >= bs) + next = blk; + + if (be == s) + before = blk; + + if (e == bs) + after = blk; + + /* If both are not null, break now */ + if (before != NULL && after != NULL) + break; + } + + /* Now check if they are really adjacent */ + if (before != NULL && s != (unsigned long)before->start + before->size) + before = NULL; + + if (after != NULL && e != (unsigned long)after->start) + after = NULL; + + /* No coalescing; list insert and return */ + if (before == NULL && after == NULL) { + + if (next != NULL) + list_add(&blkn->list, &next->list); + else + list_add(&blkn->list, &info->free_list); + + return; + } + + /* We don't need it anymore */ + release_slot(info, blkn); + + /* Grow the before block */ + if (before != NULL && after == NULL) { + before->size += size; + return; + } + + /* Grow the after block backwards */ + if (before == NULL && after != NULL) { + after->start = (int8_t *)after->start - size; + after->size += size; + return; + } + + /* Grow the before block, and release the after block */ + before->size += size + after->size; + list_del(&after->list); + release_slot(info, after); +} + +static void attach_taken_block(rh_info_t * info, rh_block_t * blkn) +{ + rh_block_t *blk; + struct list_head *l; + + /* Find the block immediately before the given one (if any) */ + list_for_each(l, &info->taken_list) { + blk = list_entry(l, rh_block_t, list); + if (blk->start > blkn->start) { + list_add_tail(&blkn->list, &blk->list); + return; + } + } + + list_add_tail(&blkn->list, &info->taken_list); +} + +/* + * Create a remote heap dynamically. Note that no memory for the blocks + * are allocated. It will upon the first allocation + */ +rh_info_t *rh_create(unsigned int alignment) +{ + rh_info_t *info; + + /* Alignment must be a power of two */ + if ((alignment & (alignment - 1)) != 0) + return ERR_PTR(-EINVAL); + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) + return ERR_PTR(-ENOMEM); + + info->alignment = alignment; + + /* Initially everything as empty */ + info->block = NULL; + info->max_blocks = 0; + info->empty_slots = 0; + info->flags = 0; + + INIT_LIST_HEAD(&info->empty_list); + INIT_LIST_HEAD(&info->free_list); + INIT_LIST_HEAD(&info->taken_list); + + return info; +} + +/* + * Destroy a dynamically created remote heap. Deallocate only if the areas + * are not static + */ +void rh_destroy(rh_info_t * info) +{ + if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL) + kfree(info->block); + + if ((info->flags & RHIF_STATIC_INFO) == 0) + kfree(info); +} + +/* + * Initialize in place a remote heap info block. This is needed to support + * operation very early in the startup of the kernel, when it is not yet safe + * to call kmalloc. + */ +void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks, + rh_block_t * block) +{ + int i; + rh_block_t *blk; + + /* Alignment must be a power of two */ + if ((alignment & (alignment - 1)) != 0) + return; + + info->alignment = alignment; + + /* Initially everything as empty */ + info->block = block; + info->max_blocks = max_blocks; + info->empty_slots = max_blocks; + info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK; + + INIT_LIST_HEAD(&info->empty_list); + INIT_LIST_HEAD(&info->free_list); + INIT_LIST_HEAD(&info->taken_list); + + /* Add all new blocks to the free list */ + for (i = 0, blk = block; i < max_blocks; i++, blk++) + list_add(&blk->list, &info->empty_list); +} + +/* Attach a free memory region, coalesces regions if adjuscent */ +int rh_attach_region(rh_info_t * info, void *start, int size) +{ + rh_block_t *blk; + unsigned long s, e, m; + int r; + + /* The region must be aligned */ + s = (unsigned long)start; + e = s + size; + m = info->alignment - 1; + + /* Round start up */ + s = (s + m) & ~m; + + /* Round end down */ + e = e & ~m; + + /* Take final values */ + start = (void *)s; + size = (int)(e - s); + + /* Grow the blocks, if needed */ + r = assure_empty(info, 1); + if (r < 0) + return r; + + blk = get_slot(info); + blk->start = start; + blk->size = size; + blk->owner = NULL; + + attach_free_block(info, blk); + + return 0; +} + +/* Detatch given address range, splits free block if needed. */ +void *rh_detach_region(rh_info_t * info, void *start, int size) +{ + struct list_head *l; + rh_block_t *blk, *newblk; + unsigned long s, e, m, bs, be; + + /* Validate size */ + if (size <= 0) + return ERR_PTR(-EINVAL); + + /* The region must be aligned */ + s = (unsigned long)start; + e = s + size; + m = info->alignment - 1; + + /* Round start up */ + s = (s + m) & ~m; + + /* Round end down */ + e = e & ~m; + + if (assure_empty(info, 1) < 0) + return ERR_PTR(-ENOMEM); + + blk = NULL; + list_for_each(l, &info->free_list) { + blk = list_entry(l, rh_block_t, list); + /* The range must lie entirely inside one free block */ + bs = (unsigned long)blk->start; + be = (unsigned long)blk->start + blk->size; + if (s >= bs && e <= be) + break; + blk = NULL; + } + + if (blk == NULL) + return ERR_PTR(-ENOMEM); + + /* Perfect fit */ + if (bs == s && be == e) { + /* Delete from free list, release slot */ + list_del(&blk->list); + release_slot(info, blk); + return (void *)s; + } + + /* blk still in free list, with updated start and/or size */ + if (bs == s || be == e) { + if (bs == s) + blk->start = (int8_t *)blk->start + size; + blk->size -= size; + + } else { + /* The front free fragment */ + blk->size = s - bs; + + /* the back free fragment */ + newblk = get_slot(info); + newblk->start = (void *)e; + newblk->size = be - e; + + list_add(&newblk->list, &blk->list); + } + + return (void *)s; +} + +void *rh_alloc(rh_info_t * info, int size, const char *owner) +{ + struct list_head *l; + rh_block_t *blk; + rh_block_t *newblk; + void *start; + + /* Validate size */ + if (size <= 0) + return ERR_PTR(-EINVAL); + + /* Align to configured alignment */ + size = (size + (info->alignment - 1)) & ~(info->alignment - 1); + + if (assure_empty(info, 1) < 0) + return ERR_PTR(-ENOMEM); + + blk = NULL; + list_for_each(l, &info->free_list) { + blk = list_entry(l, rh_block_t, list); + if (size <= blk->size) + break; + blk = NULL; + } + + if (blk == NULL) + return ERR_PTR(-ENOMEM); + + /* Just fits */ + if (blk->size == size) { + /* Move from free list to taken list */ + list_del(&blk->list); + blk->owner = owner; + start = blk->start; + + attach_taken_block(info, blk); + + return start; + } + + newblk = get_slot(info); + newblk->start = blk->start; + newblk->size = size; + newblk->owner = owner; + + /* blk still in free list, with updated start, size */ + blk->start = (int8_t *)blk->start + size; + blk->size -= size; + + start = newblk->start; + + attach_taken_block(info, newblk); + + return start; +} + +/* allocate at precisely the given address */ +void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) +{ + struct list_head *l; + rh_block_t *blk, *newblk1, *newblk2; + unsigned long s, e, m, bs, be; + + /* Validate size */ + if (size <= 0) + return ERR_PTR(-EINVAL); + + /* The region must be aligned */ + s = (unsigned long)start; + e = s + size; + m = info->alignment - 1; + + /* Round start up */ + s = (s + m) & ~m; + + /* Round end down */ + e = e & ~m; + + if (assure_empty(info, 2) < 0) + return ERR_PTR(-ENOMEM); + + blk = NULL; + list_for_each(l, &info->free_list) { + blk = list_entry(l, rh_block_t, list); + /* The range must lie entirely inside one free block */ + bs = (unsigned long)blk->start; + be = (unsigned long)blk->start + blk->size; + if (s >= bs && e <= be) + break; + } + + if (blk == NULL) + return ERR_PTR(-ENOMEM); + + /* Perfect fit */ + if (bs == s && be == e) { + /* Move from free list to taken list */ + list_del(&blk->list); + blk->owner = owner; + + start = blk->start; + attach_taken_block(info, blk); + + return start; + + } + + /* blk still in free list, with updated start and/or size */ + if (bs == s || be == e) { + if (bs == s) + blk->start = (int8_t *)blk->start + size; + blk->size -= size; + + } else { + /* The front free fragment */ + blk->size = s - bs; + + /* The back free fragment */ + newblk2 = get_slot(info); + newblk2->start = (void *)e; + newblk2->size = be - e; + + list_add(&newblk2->list, &blk->list); + } + + newblk1 = get_slot(info); + newblk1->start = (void *)s; + newblk1->size = e - s; + newblk1->owner = owner; + + start = newblk1->start; + attach_taken_block(info, newblk1); + + return start; +} + +int rh_free(rh_info_t * info, void *start) +{ + rh_block_t *blk, *blk2; + struct list_head *l; + int size; + + /* Linear search for block */ + blk = NULL; + list_for_each(l, &info->taken_list) { + blk2 = list_entry(l, rh_block_t, list); + if (start < blk2->start) + break; + blk = blk2; + } + + if (blk == NULL || start > (blk->start + blk->size)) + return -EINVAL; + + /* Remove from taken list */ + list_del(&blk->list); + + /* Get size of freed block */ + size = blk->size; + attach_free_block(info, blk); + + return size; +} + +int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) +{ + rh_block_t *blk; + struct list_head *l; + struct list_head *h; + int nr; + + switch (what) { + + case RHGS_FREE: + h = &info->free_list; + break; + + case RHGS_TAKEN: + h = &info->taken_list; + break; + + default: + return -EINVAL; + } + + /* Linear search for block */ + nr = 0; + list_for_each(l, h) { + blk = list_entry(l, rh_block_t, list); + if (stats != NULL && nr < max_stats) { + stats->start = blk->start; + stats->size = blk->size; + stats->owner = blk->owner; + stats++; + } + nr++; + } + + return nr; +} + +int rh_set_owner(rh_info_t * info, void *start, const char *owner) +{ + rh_block_t *blk, *blk2; + struct list_head *l; + int size; + + /* Linear search for block */ + blk = NULL; + list_for_each(l, &info->taken_list) { + blk2 = list_entry(l, rh_block_t, list); + if (start < blk2->start) + break; + blk = blk2; + } + + if (blk == NULL || start > (blk->start + blk->size)) + return -EINVAL; + + blk->owner = owner; + size = blk->size; + + return size; +} + +void rh_dump(rh_info_t * info) +{ + static rh_stats_t st[32]; /* XXX maximum 32 blocks */ + int maxnr; + int i, nr; + + maxnr = ARRAY_SIZE(st); + + printk(KERN_INFO + "info @0x%p (%d slots empty / %d max)\n", + info, info->empty_slots, info->max_blocks); + + printk(KERN_INFO " Free:\n"); + nr = rh_get_stats(info, RHGS_FREE, maxnr, st); + if (nr > maxnr) + nr = maxnr; + for (i = 0; i < nr; i++) + printk(KERN_INFO + " 0x%p-0x%p (%u)\n", + st[i].start, (int8_t *) st[i].start + st[i].size, + st[i].size); + printk(KERN_INFO "\n"); + + printk(KERN_INFO " Taken:\n"); + nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st); + if (nr > maxnr) + nr = maxnr; + for (i = 0; i < nr; i++) + printk(KERN_INFO + " 0x%p-0x%p (%u) %s\n", + st[i].start, (int8_t *) st[i].start + st[i].size, + st[i].size, st[i].owner != NULL ? st[i].owner : ""); + printk(KERN_INFO "\n"); +} + +void rh_dump_blk(rh_info_t * info, rh_block_t * blk) +{ + printk(KERN_INFO + "blk @0x%p: 0x%p-0x%p (%u)\n", + blk, blk->start, (int8_t *) blk->start + blk->size, blk->size); +} diff --git a/trunk/arch/ppc/platforms/mpc866ads_setup.c b/trunk/arch/ppc/platforms/mpc866ads_setup.c index bf72204125c5..7ce5364fdb3b 100644 --- a/trunk/arch/ppc/platforms/mpc866ads_setup.c +++ b/trunk/arch/ppc/platforms/mpc866ads_setup.c @@ -1,4 +1,4 @@ -/*arch/ppc/platforms/mpc866ads_setup.c +/*arch/ppc/platforms/mpc866ads-setup.c * * Platform setup for the Freescale mpc866ads board * diff --git a/trunk/arch/ppc/syslib/cpm2_common.c b/trunk/arch/ppc/syslib/cpm2_common.c index 6cd859d7721f..cbac44b1620c 100644 --- a/trunk/arch/ppc/syslib/cpm2_common.c +++ b/trunk/arch/ppc/syslib/cpm2_common.c @@ -136,14 +136,15 @@ static void cpm2_dpinit(void) * varies with the processor and the microcode patches activated. * But the following should be at least safe. */ - rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE); + rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, + CPM_DATAONLY_SIZE); } /* This function returns an index into the DPRAM area. */ -unsigned long cpm_dpalloc(uint size, uint align) +uint cpm_dpalloc(uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); @@ -151,17 +152,17 @@ unsigned long cpm_dpalloc(uint size, uint align) start = rh_alloc(&cpm_dpmem_info, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc); -int cpm_dpfree(unsigned long offset) +int cpm_dpfree(uint offset) { int ret; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); - ret = rh_free(&cpm_dpmem_info, offset); + ret = rh_free(&cpm_dpmem_info, (void *)offset); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); return ret; @@ -169,17 +170,17 @@ int cpm_dpfree(unsigned long offset) EXPORT_SYMBOL(cpm_dpfree); /* not sure if this is ever needed */ -unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align) +uint cpm_dpalloc_fixed(uint offset, uint size, uint align) { - unsigned long start; + void *start; unsigned long flags; spin_lock_irqsave(&cpm_dpmem_lock, flags); cpm_dpmem_info.alignment = align; - start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc"); + start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc"); spin_unlock_irqrestore(&cpm_dpmem_lock, flags); - return start; + return (uint)start; } EXPORT_SYMBOL(cpm_dpalloc_fixed); @@ -189,7 +190,7 @@ void cpm_dpdump(void) } EXPORT_SYMBOL(cpm_dpdump); -void *cpm_dpram_addr(unsigned long offset) +void *cpm_dpram_addr(uint offset) { return (void *)&cpm2_immr->im_dprambase[offset]; } diff --git a/trunk/arch/ppc/syslib/ipic.c b/trunk/arch/ppc/syslib/ipic.c index 9192777d0f78..10659c24b1be 100644 --- a/trunk/arch/ppc/syslib/ipic.c +++ b/trunk/arch/ppc/syslib/ipic.c @@ -1,5 +1,5 @@ /* - * arch/ppc/syslib/ipic.c + * include/asm-ppc/ipic.c * * IPIC routines implementations. * diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 098c62c29f9c..1a84719be264 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -4,23 +4,27 @@ # config MMU - def_bool y + bool + default y config ZONE_DMA def_bool y depends on 64BIT config LOCKDEP_SUPPORT - def_bool y + bool + default y config STACKTRACE_SUPPORT - def_bool y + bool + default y config RWSEM_GENERIC_SPINLOCK bool config RWSEM_XCHGADD_ALGORITHM - def_bool y + bool + default y config ARCH_HAS_ILOG2_U32 bool @@ -31,7 +35,8 @@ config ARCH_HAS_ILOG2_U64 default n config GENERIC_HWEIGHT - def_bool y + bool + default y config GENERIC_TIME def_bool y @@ -50,7 +55,8 @@ config NO_DMA mainmenu "Linux Kernel Configuration" config S390 - def_bool y + bool + default y source "init/Kconfig" @@ -274,10 +280,6 @@ config WARN_STACK_SIZE config ARCH_POPULATES_NODE_MAP def_bool y -comment "Kernel preemption" - -source "kernel/Kconfig.preempt" - source "mm/Kconfig" config HOLES_IN_ZONE @@ -318,6 +320,17 @@ config QDIO_DEBUG comment "Misc" +config PREEMPT + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say N if you are unsure. + config IPL bool "Builtin IPL record support" help @@ -475,8 +488,6 @@ config APPLDATA_NET_SUM This can also be compiled as a module, which will be called appldata_net_sum.o. -source kernel/Kconfig.hz - config NO_IDLE_HZ bool "No HZ timer ticks in idle" help @@ -524,12 +535,18 @@ endmenu source "net/Kconfig" config PCMCIA - def_bool n + bool + default n -config CCW - def_bool y +source "drivers/base/Kconfig" + +source "drivers/connector/Kconfig" + +source "drivers/scsi/Kconfig" + +source "drivers/s390/Kconfig" -source "drivers/Kconfig" +source "drivers/net/Kconfig" source "fs/Kconfig" diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index 81a2b92ab0c2..ee89b33145d5 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -567,11 +567,9 @@ appldata_cpu_notify(struct notifier_block *self, { switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: appldata_online_cpu((long) hcpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: appldata_offline_cpu((long) hcpu); break; default: diff --git a/trunk/arch/s390/crypto/Kconfig b/trunk/arch/s390/crypto/Kconfig index d1defbbfcd81..99ff9f08e4d7 100644 --- a/trunk/arch/s390/crypto/Kconfig +++ b/trunk/arch/s390/crypto/Kconfig @@ -54,7 +54,7 @@ config S390_PRNG default "m" help Select this option if you want to use the s390 pseudo random number - generator. The PRNG is part of the cryptographic processor functions + generator. The PRNG is part of the cryptograhic processor functions and uses triple-DES to generate secure random numbers like the ANSI X9.17 standard. The PRNG is usable via the char device /dev/prandom. diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 485b60c1983c..0e4da8a7d826 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21 -# Thu May 10 15:18:19 2007 +# Linux kernel version: 2.6.21-rc1 +# Wed Feb 21 10:44:30 2007 # CONFIG_MMU=y CONFIG_ZONE_DMA=y @@ -14,7 +14,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_BUG=y CONFIG_NO_IOMEM=y -CONFIG_NO_DMA=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -42,11 +41,9 @@ CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y @@ -63,14 +60,12 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set +CONFIG_VM_EVENT_COUNTERS=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -133,14 +128,6 @@ CONFIG_CHECK_STACK=y CONFIG_STACK_GUARD=256 # CONFIG_WARN_STACK is not set CONFIG_ARCH_POPULATES_NODE_MAP=y - -# -# Kernel preemption -# -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_BKL=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -163,6 +150,7 @@ CONFIG_QDIO=y # # Misc # +CONFIG_PREEMPT=y CONFIG_IPL=y # CONFIG_IPL_TAPE is not set CONFIG_IPL_VM=y @@ -175,11 +163,6 @@ CONFIG_PFAULT=y CONFIG_VIRT_TIMER=y CONFIG_VIRT_CPU_ACCOUNTING=y # CONFIG_APPLDATA_BASE is not set -CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y CONFIG_S390_HYPFS_FS=y @@ -194,6 +177,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -232,7 +216,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set @@ -257,12 +240,7 @@ CONFIG_IPV6_SIT=y # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y +# CONFIG_IP_SCTP is not set # # TIPC Configuration (EXPERIMENTAL) @@ -285,6 +263,9 @@ CONFIG_SCTP_HMAC_MD5=y # CONFIG_NET_SCHED=y CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set # # Queueing/Scheduling @@ -327,14 +308,11 @@ CONFIG_NET_ESTIMATOR=y # # CONFIG_NET_PKTGEN is not set # CONFIG_NET_TCPPROBE is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_RFKILL is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # CONFIG_PCMCIA is not set -CONFIG_CCW=y - -# -# Device Drivers -# # # Generic Driver Options @@ -351,37 +329,6 @@ CONFIG_SYS_HYPERVISOR=y # # CONFIG_CONNECTOR is not set -# -# Block devices -# -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set - -# -# S/390 block device drivers -# -CONFIG_BLK_DEV_XPRAM=m -# CONFIG_DCSSBLK is not set -CONFIG_DASD=y -CONFIG_DASD_PROFILE=y -CONFIG_DASD_ECKD=y -CONFIG_DASD_FBA=y -CONFIG_DASD_DIAG=y -CONFIG_DASD_EER=y - -# -# Misc devices -# -# CONFIG_BLINK is not set - # # SCSI device support # @@ -409,7 +356,6 @@ CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -426,6 +372,34 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y +CONFIG_CCW=y + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_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 + +# +# S/390 block device drivers +# +CONFIG_BLK_DEV_XPRAM=m +# CONFIG_DCSSBLK is not set +CONFIG_DASD=y +CONFIG_DASD_PROFILE=y +CONFIG_DASD_ECKD=y +CONFIG_DASD_FBA=y +CONFIG_DASD_DIAG=y +CONFIG_DASD_EER=y +# CONFIG_ATA_OVER_ETH is not set # # Multi-device support (RAID and LVM) @@ -447,7 +421,56 @@ CONFIG_DM_MIRROR=y CONFIG_DM_ZERO=y CONFIG_DM_MULTIPATH=y # CONFIG_DM_MULTIPATH_EMC is not set -# CONFIG_DM_DELAY is not set + +# +# Character device drivers +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +# CONFIG_HANGCHECK_TIMER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set + +# +# S/390 character device drivers +# +CONFIG_TN3270=y +CONFIG_TN3270_TTY=y +CONFIG_TN3270_FS=m +CONFIG_TN3270_CONSOLE=y +CONFIG_TN3215=y +CONFIG_TN3215_CONSOLE=y +CONFIG_CCW_CONSOLE=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_VT220_TTY=y +CONFIG_SCLP_VT220_CONSOLE=y +CONFIG_SCLP_CPI=m +CONFIG_S390_TAPE=m + +# +# S/390 tape interface support +# +CONFIG_S390_TAPE_BLOCK=y + +# +# S/390 tape hardware support +# +CONFIG_S390_TAPE_34XX=m +# CONFIG_S390_TAPE_3590 is not set +# CONFIG_VMLOGRDR is not set +# CONFIG_VMCP is not set +# CONFIG_MONREADER is not set +CONFIG_MONWRITER=m + +# +# Cryptographic devices +# +CONFIG_ZCRYPT=m +# CONFIG_ZCRYPT_MONOLITHIC is not set # # Network device support @@ -458,6 +481,10 @@ CONFIG_BONDING=m CONFIG_EQUALIZER=m CONFIG_TUN=m +# +# PHY device support +# + # # Ethernet (10 or 100Mbit) # @@ -471,13 +498,17 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_MLX4_DEBUG=y # # Token Ring devices # # CONFIG_TR is not set +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + # # Wan interfaces # @@ -505,56 +536,6 @@ CONFIG_CCWGROUP=y # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set -# -# Character devices -# -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_HW_RANDOM=m -# CONFIG_R3964 is not set -CONFIG_RAW_DRIVER=m -CONFIG_MAX_RAW_DEVS=256 -# CONFIG_HANGCHECK_TIMER is not set - -# -# S/390 character device drivers -# -CONFIG_TN3270=y -CONFIG_TN3270_TTY=y -CONFIG_TN3270_FS=m -CONFIG_TN3270_CONSOLE=y -CONFIG_TN3215=y -CONFIG_TN3215_CONSOLE=y -CONFIG_CCW_CONSOLE=y -CONFIG_SCLP=y -CONFIG_SCLP_TTY=y -CONFIG_SCLP_CONSOLE=y -CONFIG_SCLP_VT220_TTY=y -CONFIG_SCLP_VT220_CONSOLE=y -CONFIG_SCLP_CPI=m -CONFIG_S390_TAPE=m - -# -# S/390 tape interface support -# -CONFIG_S390_TAPE_BLOCK=y - -# -# S/390 tape hardware support -# -CONFIG_S390_TAPE_34XX=m -# CONFIG_S390_TAPE_3590 is not set -# CONFIG_VMLOGRDR is not set -# CONFIG_VMCP is not set -# CONFIG_MONREADER is not set -CONFIG_MONWRITER=m - # # File systems # @@ -647,7 +628,6 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -678,7 +658,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set # # Native Language Support @@ -689,6 +668,8 @@ CONFIG_MSDOS_PARTITION=y # Distributed Lock Manager # CONFIG_DLM=m +CONFIG_DLM_TCP=y +# CONFIG_DLM_SCTP is not set # CONFIG_DLM_DEBUG is not set # @@ -712,6 +693,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set @@ -747,13 +729,12 @@ CONFIG_FORCED_INLINING=y CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=m CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_HMAC=m +# CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=m +# CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -764,7 +745,6 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_DES is not set CONFIG_CRYPTO_FCRYPT=m # CONFIG_CRYPTO_BLOWFISH is not set @@ -791,8 +771,6 @@ CONFIG_CRYPTO_CAMELLIA=m # CONFIG_CRYPTO_DES_S390 is not set # CONFIG_CRYPTO_AES_S390 is not set CONFIG_S390_PRNG=m -CONFIG_ZCRYPT=m -# CONFIG_ZCRYPT_MONOLITHIC is not set # # Library routines diff --git a/trunk/arch/s390/hypfs/inode.c b/trunk/arch/s390/hypfs/inode.c index 8e1ea1c40128..ba5d3167df0d 100644 --- a/trunk/arch/s390/hypfs/inode.c +++ b/trunk/arch/s390/hypfs/inode.c @@ -477,7 +477,7 @@ static int __init hypfs_init(void) goto fail_diag; } } - kobj_set_kset_s(&s390_subsys, hypervisor_subsys); + kset_set_kset_s(&s390_subsys, hypervisor_subsys); rc = subsystem_register(&s390_subsys); if (rc) goto fail_sysfs; diff --git a/trunk/arch/s390/kernel/asm-offsets.c b/trunk/arch/s390/kernel/asm-offsets.c index 1375f8a4469e..ec514fe5ccd0 100644 --- a/trunk/arch/s390/kernel/asm-offsets.c +++ b/trunk/arch/s390/kernel/asm-offsets.c @@ -15,7 +15,7 @@ int main(void) { - DEFINE(__THREAD_info, offsetof(struct task_struct, stack),); + DEFINE(__THREAD_info, offsetof(struct task_struct, thread_info),); DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),); DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),); DEFINE(__THREAD_mm_segment, diff --git a/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 367caf92ea78..0ea048d350d8 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/arch/s390/kernel/ipl.c @@ -816,23 +816,23 @@ static int __init ipl_register_fcp_files(void) { int rc; - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); if (rc) goto out; - rc = sysfs_create_bin_file(&ipl_subsys.kobj, + 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.kobj, + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, &ipl_scp_data_attr); if (!rc) goto out; - sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr); + sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); out_ipl_parm: - sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group); + sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); out: return rc; } @@ -846,7 +846,7 @@ static int __init ipl_init(void) return rc; switch (ipl_info.type) { case IPL_TYPE_CCW: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); break; case IPL_TYPE_FCP: @@ -854,11 +854,11 @@ static int __init ipl_init(void) rc = ipl_register_fcp_files(); break; case IPL_TYPE_NSS: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_nss_attr_group); break; default: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_unknown_attr_group); break; } @@ -885,7 +885,7 @@ static int __init reipl_nss_init(void) if (!MACHINE_IS_VM) return 0; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group); if (rc) return rc; strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); @@ -900,7 +900,7 @@ static int __init reipl_ccw_init(void) reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); if (!reipl_block_ccw) return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group); if (rc) { free_page((unsigned long)reipl_block_ccw); return rc; @@ -938,7 +938,7 @@ static int __init reipl_fcp_init(void) reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); if (!reipl_block_fcp) return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group); if (rc) { free_page((unsigned long)reipl_block_fcp); return rc; @@ -990,7 +990,7 @@ static int __init dump_ccw_init(void) dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); if (!dump_block_ccw) return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group); + rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group); if (rc) { free_page((unsigned long)dump_block_ccw); return rc; @@ -1014,7 +1014,7 @@ static int __init dump_fcp_init(void) dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); if (!dump_block_fcp) return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group); + rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group); if (rc) { free_page((unsigned long)dump_block_fcp); return rc; diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 09f028a3266b..b7977027a28f 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -789,12 +789,10 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: if (sysdev_create_file(s, &attr_capability)) return NOTIFY_BAD; break; case CPU_DEAD: - case CPU_DEAD_FROZEN: sysdev_remove_file(s, &attr_capability); break; } diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index d855cdbf8fb8..8b924b359774 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -253,10 +253,7 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs, unsigned long address, unsigned long error_code) { u16 instruction; - int rc; -#ifdef CONFIG_COMPAT - int compat; -#endif + int rc, compat; pagefault_disable(); rc = __get_user(instruction, (u16 __user *) regs->psw.addr); diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 038179ecf6a9..d74eb120a9c6 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -52,9 +52,6 @@ config GENERIC_IOMAP config GENERIC_TIME def_bool n -config GENERIC_CLOCKEVENTS - def_bool n - config SYS_SUPPORTS_APM_EMULATION bool @@ -439,11 +436,11 @@ endmenu menu "Timer and clock configuration" +if !GENERIC_TIME + config SH_TMU bool "TMU timer support" depends on CPU_SH3 || CPU_SH4 - select GENERIC_TIME - select GENERIC_CLOCKEVENTS default y help This enables the use of the TMU as the system timer. @@ -462,6 +459,8 @@ config SH_MTU2 help This enables the use of the MTU2 as the system timer. +endif + config SH_TIMER_IRQ int default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 @@ -469,6 +468,24 @@ config SH_TIMER_IRQ default "140" if CPU_SUBTYPE_SH7206 default "16" +config NO_IDLE_HZ + bool "Dynamic tick timer" + help + Select this option if you want to disable continuous timer ticks + and have them programmed to occur as required. This option saves + power as the system can remain in idle state for longer. + + By default dynamic tick is disabled during the boot, and can be + manually enabled with: + + echo 1 > /sys/devices/system/timer/timer0/dyn_tick + + Alternatively, if you want dynamic tick automatically enabled + during boot, pass "dyntick=enable" via the kernel command string. + + Please note that dynamic tick may affect the accuracy of + timekeeping on some platforms depending on the implementation. + config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 @@ -492,8 +509,6 @@ config SH_CLK_MD help MD2 - MD0 pin setting. -source "kernel/time/Kconfig" - endmenu menu "CPU Frequency scaling" diff --git a/trunk/arch/sh/boards/landisk/setup.c b/trunk/arch/sh/boards/landisk/setup.c index 4058b4f50d44..a83a5d9587bb 100644 --- a/trunk/arch/sh/boards/landisk/setup.c +++ b/trunk/arch/sh/boards/landisk/setup.c @@ -93,7 +93,6 @@ static void __init landisk_setup(char **cmdline_p) */ struct sh_machine_vector mv_landisk __initmv = { .mv_name = "LANDISK", - .mv_nr_irqs = 72, .mv_setup = landisk_setup, .mv_init_irq = init_landisk_IRQ, }; diff --git a/trunk/arch/sh/boards/se/7751/setup.c b/trunk/arch/sh/boards/se/7751/setup.c index 52c7bfa57c2c..770defed9c4a 100644 --- a/trunk/arch/sh/boards/se/7751/setup.c +++ b/trunk/arch/sh/boards/se/7751/setup.c @@ -1,5 +1,5 @@ /* - * linux/arch/sh/boards/se/7751/setup.c + * linux/arch/sh/kernel/setup_7751se.c * * Copyright (C) 2000 Kazumoto Kojima * diff --git a/trunk/arch/sh/drivers/Makefile b/trunk/arch/sh/drivers/Makefile index e13f06bebd92..6cb92676c5fc 100644 --- a/trunk/arch/sh/drivers/Makefile +++ b/trunk/arch/sh/drivers/Makefile @@ -2,9 +2,8 @@ # Makefile for the Linux SuperH-specific device drivers. # -obj-y += dma/ - obj-$(CONFIG_PCI) += pci/ +obj-$(CONFIG_SH_DMA) += dma/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_PUSH_SWITCH) += push-switch.o obj-$(CONFIG_HEARTBEAT) += heartbeat.o diff --git a/trunk/arch/sh/drivers/dma/Kconfig b/trunk/arch/sh/drivers/dma/Kconfig index 99935f9daf4b..defc13c37d48 100644 --- a/trunk/arch/sh/drivers/dma/Kconfig +++ b/trunk/arch/sh/drivers/dma/Kconfig @@ -1,12 +1,12 @@ menu "DMA support" -config SH_DMA_API - bool - config SH_DMA - bool "SuperH on-chip DMA controller (DMAC) support" - select SH_DMA_API - default n + bool "DMA controller (DMAC) support" + help + Selecting this option will provide same API as PC's Direct Memory + Access Controller(8237A) for SuperH DMAC. + + If unsure, say N. config NR_ONCHIP_DMA_CHANNELS depends on SH_DMA @@ -53,12 +53,4 @@ config DMA_PAGE_OPS_CHANNEL in case channel 3 is unavailable. On the SH4, channels 1,2, and 3 are dual-address capable. -config SH_DMABRG - bool "SH7760 DMABRG support" - depends on CPU_SUBTYPE_SH7760 - help - The DMABRG does data transfers from main memory to Audio/USB units - of the SH7760. - Say Y if you want to use Audio/USB DMA on your SH7760 board. - endmenu diff --git a/trunk/arch/sh/drivers/dma/Makefile b/trunk/arch/sh/drivers/dma/Makefile index 1ac812d24488..db1295d32268 100644 --- a/trunk/arch/sh/drivers/dma/Makefile +++ b/trunk/arch/sh/drivers/dma/Makefile @@ -2,8 +2,8 @@ # Makefile for the SuperH DMA specific kernel interface routines under Linux. # -obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o +obj-y += dma-api.o obj-$(CONFIG_ISA_DMA_API) += dma-isa.o +obj-$(CONFIG_SYSFS) += dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o -obj-$(CONFIG_SH_DMABRG) += dmabrg.o diff --git a/trunk/arch/sh/drivers/dma/dmabrg.c b/trunk/arch/sh/drivers/dma/dmabrg.c deleted file mode 100644 index 9d0a29370f21..000000000000 --- a/trunk/arch/sh/drivers/dma/dmabrg.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SH7760 DMABRG IRQ handling - * - * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss - * licensed under the GPLv2. - * - */ - -#include -#include -#include -#include -#include - -/* - * The DMABRG is a special DMA unit within the SH7760. It does transfers - * from USB-SRAM/Audio units to main memory (and also the LCDC; but that - * part is sensibly placed in the LCDC registers and requires no irqs) - * It has 3 IRQ lines which trigger 10 events, and works independently - * from the traditional SH DMAC (although it blocks usage of DMAC 0) - * - * BRGIRQID | component | dir | meaning | source - * ----------------------------------------------------- - * 0 | USB-DMA | ... | xfer done | DMABRGI1 - * 1 | USB-UAE | ... | USB addr err.| DMABRGI0 - * 2 | HAC0/SSI0 | play| all done | DMABRGI1 - * 3 | HAC0/SSI0 | play| half done | DMABRGI2 - * 4 | HAC0/SSI0 | rec | all done | DMABRGI1 - * 5 | HAC0/SSI0 | rec | half done | DMABRGI2 - * 6 | HAC1/SSI1 | play| all done | DMABRGI1 - * 7 | HAC1/SSI1 | play| half done | DMABRGI2 - * 8 | HAC1/SSI1 | rec | all done | DMABRGI1 - * 9 | HAC1/SSI1 | rec | half done | DMABRGI2 - * - * all can be enabled/disabled in the DMABRGCR register, - * as well as checked if they occured. - * - * DMABRGI0 services USB DMA Address errors, but it still must be - * enabled/acked in the DMABRGCR register. USB-DMA complete indicator - * is grouped together with the audio buffer end indicators, too bad... - * - * DMABRGCR: Bits 31-24: audio-dma ENABLE flags, - * Bits 23-16: audio-dma STATUS flags, - * Bits 9-8: USB error/xfer ENABLE, - * Bits 1-0: USB error/xfer STATUS. - * Ack an IRQ by writing 0 to the STATUS flag. - * Mask IRQ by writing 0 to ENABLE flag. - * - * Usage is almost like with any other IRQ: - * dmabrg_request_irq(BRGIRQID, handler, data) - * dmabrg_free_irq(BRGIRQID) - * - * handler prototype: void brgirqhandler(void *data) - */ - -#define DMARSRA 0xfe090000 -#define DMAOR 0xffa00040 -#define DMACHCR0 0xffa0000c -#define DMABRGCR 0xfe3c0000 - -#define DMAOR_BRG 0x0000c000 -#define DMAOR_DMEN 0x00000001 - -#define DMABRGI0 68 -#define DMABRGI1 69 -#define DMABRGI2 70 - -struct dmabrg_handler { - void (*handler)(void *); - void *data; -} *dmabrg_handlers; - -static inline void dmabrg_call_handler(int i) -{ - dmabrg_handlers[i].handler(dmabrg_handlers[i].data); -} - -/* - * main DMABRG irq handler. It acks irqs and then - * handles every set and unmasked bit sequentially. - * No locking and no validity checks; it should be - * as fast as possible (audio!) - */ -static irqreturn_t dmabrg_irq(int irq, void *data) -{ - unsigned long dcr; - unsigned int i; - - dcr = ctrl_inl(DMABRGCR); - ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */ - dcr &= dcr >> 8; /* ignore masked */ - - /* USB stuff, get it out of the way first */ - if (dcr & 1) - dmabrg_call_handler(DMABRGIRQ_USBDMA); - if (dcr & 2) - dmabrg_call_handler(DMABRGIRQ_USBDMAERR); - - /* Audio */ - dcr >>= 16; - while (dcr) { - i = __ffs(dcr); - dcr &= dcr - 1; - dmabrg_call_handler(i + DMABRGIRQ_A0TXF); - } - return IRQ_HANDLED; -} - -static void dmabrg_disable_irq(unsigned int dmairq) -{ - unsigned long dcr; - dcr = ctrl_inl(DMABRGCR); - dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); - ctrl_outl(dcr, DMABRGCR); -} - -static void dmabrg_enable_irq(unsigned int dmairq) -{ - unsigned long dcr; - dcr = ctrl_inl(DMABRGCR); - dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); - ctrl_outl(dcr, DMABRGCR); -} - -int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*), - void *data) -{ - if ((dmairq > 9) || !handler) - return -ENOENT; - if (dmabrg_handlers[dmairq].handler) - return -EBUSY; - - dmabrg_handlers[dmairq].handler = handler; - dmabrg_handlers[dmairq].data = data; - - dmabrg_enable_irq(dmairq); - return 0; -} -EXPORT_SYMBOL_GPL(dmabrg_request_irq); - -void dmabrg_free_irq(unsigned int dmairq) -{ - if (likely(dmairq < 10)) { - dmabrg_disable_irq(dmairq); - dmabrg_handlers[dmairq].handler = NULL; - dmabrg_handlers[dmairq].data = NULL; - } -} -EXPORT_SYMBOL_GPL(dmabrg_free_irq); - -static int __init dmabrg_init(void) -{ - unsigned long or; - int ret; - - dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler), - GFP_KERNEL); - if (!dmabrg_handlers) - return -ENOMEM; - -#ifdef CONFIG_SH_DMA - /* request DMAC channel 0 before anyone else can get it */ - ret = request_dma(0, "DMAC 0 (DMABRG)"); - if (ret < 0) - printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n"); -#endif - - ctrl_outl(0, DMABRGCR); - ctrl_outl(0, DMACHCR0); - ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */ - - /* enable DMABRG mode, enable the DMAC */ - or = ctrl_inl(DMAOR); - ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR); - - ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED, - "DMABRG USB address error", NULL); - if (ret) - goto out0; - - ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED, - "DMABRG Transfer End", NULL); - if (ret) - goto out1; - - ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED, - "DMABRG Transfer Half", NULL); - if (ret == 0) - return ret; - - free_irq(DMABRGI1, 0); -out1: free_irq(DMABRGI0, 0); -out0: kfree(dmabrg_handlers); - return ret; -} -subsys_initcall(dmabrg_init); diff --git a/trunk/arch/sh/kernel/cpu/sh2a/Makefile b/trunk/arch/sh/kernel/cpu/sh2a/Makefile index 965fa2572b23..350972ae9410 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh2a/Makefile @@ -2,8 +2,9 @@ # Makefile for the Linux/SuperH SH-2A backends. # -obj-y := common.o probe.o opcode_helper.o +obj-y := common.o probe.o -common-y += $(addprefix ../sh2/, ex.o entry.o) +common-y += $(addprefix ../sh2/, ex.o) +common-y += $(addprefix ../sh2/, entry.o) obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o diff --git a/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c deleted file mode 100644 index 9704b7926d8b..000000000000 --- a/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * arch/sh/kernel/cpu/sh2a/opcode_helper.c - * - * Helper for the SH-2A 32-bit opcodes. - * - * Copyright (C) 2007 Paul Mundt - * - * 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 - -/* - * Instructions on SH are generally fixed at 16-bits, however, SH-2A - * introduces some 32-bit instructions. Since there are no real - * constraints on their use (and they can be mixed and matched), we need - * to check the instruction encoding to work out if it's a true 32-bit - * instruction or not. - * - * Presently, 32-bit opcodes have only slight variations in what the - * actual encoding looks like in the first-half of the instruction, which - * makes it fairly straightforward to differentiate from the 16-bit ones. - * - * First 16-bits of encoding Used by - * - * 0011nnnnmmmm0001 mov.b, mov.w, mov.l, fmov.d, - * fmov.s, movu.b, movu.w - * - * 0011nnnn0iii1001 bclr.b, bld.b, bset.b, bst.b, band.b, - * bandnot.b, bldnot.b, bor.b, bornot.b, - * bxor.b - * - * 0000nnnniiii0000 movi20 - * 0000nnnniiii0001 movi20s - */ -unsigned int instruction_size(unsigned int insn) -{ - /* Look for the common cases */ - switch ((insn & 0xf00f)) { - case 0x0000: /* movi20 */ - case 0x0001: /* movi20s */ - case 0x3001: /* 32-bit mov/fmov/movu variants */ - return 4; - } - - /* And the special cases.. */ - switch ((insn & 0xf08f)) { - case 0x3009: /* 32-bit b*.b bit operations */ - return 4; - } - - return 2; -} diff --git a/trunk/arch/sh/kernel/cpu/sh2a/probe.c b/trunk/arch/sh/kernel/cpu/sh2a/probe.c index f455c3509789..426f6db01fc6 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/probe.c +++ b/trunk/arch/sh/kernel/cpu/sh2a/probe.c @@ -18,7 +18,6 @@ int __init detect_cpu_and_cache_system(void) { /* Just SH7206 for now .. */ current_cpu_data.type = CPU_SH7206; - current_cpu_data.flags |= CPU_HAS_OP32; current_cpu_data.dcache.ways = 4; current_cpu_data.dcache.way_incr = (1 << 11); diff --git a/trunk/arch/sh/kernel/cpu/sh3/entry.S b/trunk/arch/sh/kernel/cpu/sh3/entry.S index 832c0b4a1e6c..f3e827f29a46 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh3/entry.S @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh3/entry.S + * arch/sh/kernel/entry.S * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt diff --git a/trunk/arch/sh/kernel/cpu/sh3/ex.S b/trunk/arch/sh/kernel/cpu/sh3/ex.S index 2b2a9e02fb75..ba3082d640b5 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/ex.S +++ b/trunk/arch/sh/kernel/cpu/sh3/ex.S @@ -1,7 +1,7 @@ /* * arch/sh/kernel/cpu/sh3/ex.S * - * The SH-3 and SH-4 exception vector table. + * The SH-3 exception vector table. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt @@ -9,6 +9,7 @@ * 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 @@ -35,12 +36,8 @@ ENTRY(exception_handling_table) .long exception_error ! address error load .long exception_error ! address error store /* 100 */ #endif -#if defined(CONFIG_SH_FPU) - .long do_fpu_error /* 120 */ -#else - .long exception_error /* 120 */ -#endif - .long exception_error /* 140 */ + .long exception_error ! fpu_exception /* 120 */ + .long exception_error /* 140 */ .long system_call ! Unconditional Trap /* 160 */ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ @@ -58,4 +55,4 @@ ENTRY(user_break_point_trap) * away offsets can be manually inserted in to their appropriate * location via set_exception_table_{evt,vec}(). */ - .balign 4096,0,4096 + .balign 4096,0,4096 diff --git a/trunk/arch/sh/kernel/cpu/sh4/Makefile b/trunk/arch/sh/kernel/cpu/sh4/Makefile index 8add10bd8268..19ca68c71884 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh4/Makefile @@ -2,10 +2,10 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := probe.o common.o -common-y += $(addprefix ../sh3/, entry.o ex.o) +obj-y := ex.o probe.o common.o +common-y += $(addprefix ../sh3/, entry.o) -obj-$(CONFIG_SH_FPU) += fpu.o +obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o # CPU subtype setup diff --git a/trunk/arch/sh/kernel/cpu/sh4/ex.S b/trunk/arch/sh/kernel/cpu/sh4/ex.S new file mode 100644 index 000000000000..ac8ab57413cc --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh4/ex.S @@ -0,0 +1,62 @@ +/* + * arch/sh/kernel/cpu/sh4/ex.S + * + * The SH-4 exception vector table. + + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 - 2006 Paul Mundt + * + * 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 + + .align 2 + .data + +ENTRY(exception_handling_table) + .long exception_error /* 000 */ + .long exception_error +#if defined(CONFIG_MMU) + .long tlb_miss_load /* 040 */ + .long tlb_miss_store + .long initial_page_write + .long tlb_protection_violation_load + .long tlb_protection_violation_store + .long address_error_load + .long address_error_store /* 100 */ +#else + .long exception_error ! tlb miss load /* 040 */ + .long exception_error ! tlb miss store + .long exception_error ! initial page write + .long exception_error ! tlb prot violation load + .long exception_error ! tlb prot violation store + .long exception_error ! address error load + .long exception_error ! address error store /* 100 */ +#endif +#if defined(CONFIG_SH_FPU) + .long do_fpu_error /* 120 */ +#else + .long exception_error /* 120 */ +#endif + .long exception_error /* 140 */ + .long system_call ! Unconditional Trap /* 160 */ + .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ + .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ +ENTRY(nmi_slot) +#if defined (CONFIG_KGDB_NMI) + .long debug_enter /* 1C0 */ ! Allow trap to debugger +#else + .long exception_none /* 1C0 */ ! Not implemented yet +#endif +ENTRY(user_break_point_trap) + .long break_point_trap /* 1E0 */ + + /* + * Pad the remainder of the table out, exceptions residing in far + * away offsets can be manually inserted in to their appropriate + * location via set_exception_table_{evt,vec}(). + */ + .balign 4096,0,4096 diff --git a/trunk/arch/sh/kernel/cpu/sh4/fpu.c b/trunk/arch/sh/kernel/cpu/sh4/fpu.c index d61dd599169f..7624677f6628 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/fpu.c +++ b/trunk/arch/sh/kernel/cpu/sh4/fpu.c @@ -16,7 +16,6 @@ #include #include #include -#include #include /* The PR (precision) bit in the FP Status Register must be clear when @@ -266,7 +265,7 @@ ieee_fpe_handler (struct pt_regs *regs) nextpc = regs->pr; finsn = *(unsigned short *) (regs->pc + 2); } else { - nextpc = regs->pc + instruction_size(insn); + nextpc = regs->pc + 2; finsn = insn; } diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c index 6d5ba373a75e..2fa5cb2ae68d 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh73180.c + * arch/sh/kernel/cpu/sh4/clock-sh73180.c * * SH73180 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 7adc4f16e95a..1707a213f0cf 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7343.c + * arch/sh/kernel/cpu/sh4/clock-sh7343.c * * SH7343/SH7722 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c index 8e236062c721..c8694bac6477 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7770.c + * arch/sh/kernel/cpu/sh4/clock-sh7770.c * * SH7770 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c index 01f3da619d3d..9e6a216750c8 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7780.c + * arch/sh/kernel/cpu/sh4/clock-sh7780.c * * SH7780 support for the clock framework * diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index 6b4f5748d0be..329b3f3051de 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -15,12 +15,9 @@ #include #include #include -#include -#include +#include #include #include -#include -#include #include static int hlt_counter; @@ -61,15 +58,12 @@ void cpu_idle(void) if (!idle) idle = default_idle; - tick_nohz_stop_sched_tick(); while (!need_resched()) idle(); - tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); preempt_disable(); - check_pgt_cache(); } } @@ -501,9 +495,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5, struct pt_regs *regs = RELOC_HIDE(&__regs, 0); /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; - if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff, + if (notify_die(DIE_TRAP, regs, regs->tra & 0xff, SIGTRAP) == NOTIFY_STOP) return; @@ -520,9 +514,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5, struct pt_regs *regs = RELOC_HIDE(&__regs, 0); /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; - if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, + if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff, SIGTRAP) == NOTIFY_STOP) return; diff --git a/trunk/arch/sh/kernel/setup.c b/trunk/arch/sh/kernel/setup.c index c27729135935..477d2a854fc4 100644 --- a/trunk/arch/sh/kernel/setup.c +++ b/trunk/arch/sh/kernel/setup.c @@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c) /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ static const char *cpu_flags[] = { "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", - "ptea", "llsc", "l2", "op32", NULL + "ptea", "llsc", "l2", NULL }; static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) diff --git a/trunk/arch/sh/kernel/sh_ksyms.c b/trunk/arch/sh/kernel/sh_ksyms.c index c1cfcb9f047c..fa91641c1f62 100644 --- a/trunk/arch/sh/kernel/sh_ksyms.c +++ b/trunk/arch/sh/kernel/sh_ksyms.c @@ -58,6 +58,8 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(__div64_32); + #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) /* These symbols are generated by the compiler itself */ diff --git a/trunk/arch/sh/kernel/signal.c b/trunk/arch/sh/kernel/signal.c index b32c35a7c0a3..eb0191c374b6 100644 --- a/trunk/arch/sh/kernel/signal.c +++ b/trunk/arch/sh/kernel/signal.c @@ -23,7 +23,7 @@ #include #include #include -#include + #include #include #include @@ -500,9 +500,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* fallthrough */ case -ERESTARTNOINTR: - regs->pc -= instruction_size( - ctrl_inw(regs->pc - 4)); - break; + regs->pc -= 2; } } else { /* gUSA handling */ @@ -518,8 +516,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, regs->regs[15] = regs->regs[1]; if (regs->pc < regs->regs[0]) /* Go to rewind point #1 */ - regs->pc = regs->regs[0] + offset - - instruction_size(ctrl_inw(regs->pc-4)); + regs->pc = regs->regs[0] + offset - 2; } #ifdef CONFIG_PREEMPT local_irq_restore(flags); @@ -603,9 +600,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) regs->regs[0] == -ERESTARTSYS || regs->regs[0] == -ERESTARTNOINTR) { regs->regs[0] = save_r0; - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; regs->regs[3] = __NR_restart_syscall; } } diff --git a/trunk/arch/sh/kernel/stacktrace.c b/trunk/arch/sh/kernel/stacktrace.c index d41e561be20e..4bdd2f83535d 100644 --- a/trunk/arch/sh/kernel/stacktrace.c +++ b/trunk/arch/sh/kernel/stacktrace.c @@ -17,7 +17,7 @@ /* * Save stack-backtrace addresses into a stack_trace buffer. */ -void save_stack_trace(struct stack_trace *trace) +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) { unsigned long *sp = (unsigned long *)current_stack_pointer; diff --git a/trunk/arch/sh/kernel/syscalls.S b/trunk/arch/sh/kernel/syscalls.S index 4357d1a6358f..38fc8cd3ea3a 100644 --- a/trunk/arch/sh/kernel/syscalls.S +++ b/trunk/arch/sh/kernel/syscalls.S @@ -354,4 +354,3 @@ ENTRY(sys_call_table) .long sys_move_pages .long sys_getcpu .long sys_epoll_pwait - .long sys_utimensat /* 320 */ diff --git a/trunk/arch/sh/kernel/time.c b/trunk/arch/sh/kernel/time.c index a3a67d151e52..d47e775962e9 100644 --- a/trunk/arch/sh/kernel/time.c +++ b/trunk/arch/sh/kernel/time.c @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2006 Paul Mundt * Copyright (C) 2002 M. R. Brown * * Some code taken from i386 version. @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -39,14 +38,6 @@ static int null_rtc_set_time(const time_t secs) return 0; } -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; @@ -110,7 +101,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); #endif /* !CONFIG_GENERIC_TIME */ -#ifndef CONFIG_GENERIC_CLOCKEVENTS /* last time the RTC clock got updated */ static long last_rtc_update; @@ -148,7 +138,6 @@ void handle_timer_tick(void) last_rtc_update = xtime.tv_sec - 600; } } -#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ #ifdef CONFIG_PM int timer_suspend(struct sys_device *dev, pm_message_t state) @@ -179,58 +168,136 @@ static struct sysdev_class timer_sysclass = { .resume = timer_resume, }; -static int __init timer_init_sysfs(void) +#ifdef CONFIG_NO_IDLE_HZ +static int timer_dyn_tick_enable(void) { - int ret = sysdev_class_register(&timer_sysclass); - if (ret != 0) - return ret; + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (!(dyn_tick->state & DYN_TICK_ENABLED)) { + ret = dyn_tick->enable(); + + if (ret == 0) + dyn_tick->state |= DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } - sys_timer->dev.cls = &timer_sysclass; - return sysdev_register(&sys_timer->dev); + return ret; } -device_initcall(timer_init_sysfs); -void (*board_time_init)(void); +static int timer_dyn_tick_disable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (dyn_tick->state & DYN_TICK_ENABLED) { + ret = dyn_tick->disable(); + + if (ret == 0) + dyn_tick->state &= ~DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} /* - * Shamelessly based on the MIPS and Sparc64 work. + * Reprogram the system timer for at least the calculated time interval. + * This function should be called from the idle thread with IRQs disabled, + * immediately before sleeping. */ -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; -unsigned long sh_hpt_frequency = 0; - -#define NSEC_PER_CYC_SHIFT 10 - -struct clocksource clocksource_sh = { - .name = "SuperH", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = null_hpt_read, - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void __init init_sh_clocksource(void) +void timer_dyn_reprogram(void) { - if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long next, seq, flags; + + if (!dyn_tick) return; - clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, - clocksource_sh.shift); + spin_lock_irqsave(&dyn_tick->lock, flags); + if (dyn_tick->state & DYN_TICK_ENABLED) { + next = next_timer_interrupt(); + do { + seq = read_seqbegin(&xtime_lock); + dyn_tick->reprogram(next - jiffies); + } while (read_seqretry(&xtime_lock, seq)); + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); +} + +static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) +{ + return sprintf(buf, "%i\n", + (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); +} + +static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, + size_t count) +{ + unsigned int enable = simple_strtoul(buf, NULL, 2); - timer_ticks_per_nsec_quotient = - clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); + if (enable) + timer_dyn_tick_enable(); + else + timer_dyn_tick_disable(); - clocksource_register(&clocksource_sh); + return count; } +static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); -#ifdef CONFIG_GENERIC_TIME -unsigned long long sched_clock(void) +/* + * dyntick=enable|disable + */ +static char dyntick_str[4] __initdata = ""; + +static int __init dyntick_setup(char *str) { - unsigned long long ticks = clocksource_sh.read(); - return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; + if (str) + strlcpy(dyntick_str, str, sizeof(dyntick_str)); + return 1; } + +__setup("dyntick=", dyntick_setup); +#endif + +static int __init timer_init_sysfs(void) +{ + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; + + sys_timer->dev.cls = &timer_sysclass; + ret = sysdev_register(&sys_timer->dev); + +#ifdef CONFIG_NO_IDLE_HZ + if (ret == 0 && sys_timer->dyn_tick) { + ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick); + + /* + * Turn on dynamic tick after calibrate delay + * for correct bogomips + */ + if (ret == 0 && dyntick_str[0] == 'e') + ret = timer_dyn_tick_enable(); + } #endif + return ret; +} +device_initcall(timer_init_sysfs); + +void (*board_time_init)(void); + void __init time_init(void) { if (board_time_init) @@ -249,15 +316,10 @@ void __init time_init(void) sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); - if (sys_timer->ops->read) - clocksource_sh.read = sys_timer->ops->read; - - init_sh_clocksource(); - - if (sh_hpt_frequency) - printk("Using %lu.%03lu MHz high precision timer.\n", - ((sh_hpt_frequency + 500) / 1000) / 1000, - ((sh_hpt_frequency + 500) / 1000) % 1000); +#ifdef CONFIG_NO_IDLE_HZ + if (sys_timer->dyn_tick) + spin_lock_init(&sys_timer->dyn_tick->lock); +#endif #if defined(CONFIG_SH_KGDB) /* diff --git a/trunk/arch/sh/kernel/timers/timer-tmu.c b/trunk/arch/sh/kernel/timers/timer-tmu.c index 2d997e2a5b6c..d9e3151c891e 100644 --- a/trunk/arch/sh/kernel/timers/timer-tmu.c +++ b/trunk/arch/sh/kernel/timers/timer-tmu.c @@ -1,7 +1,7 @@ /* * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support * - * Copyright (C) 2005 - 2007 Paul Mundt + * Copyright (C) 2005 Paul Mundt * * TMU handling code hacked out of arch/sh/kernel/time.c * @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,75 +25,56 @@ #include #define TMU_TOCR_INIT 0x00 -#define TMU_TCR_INIT 0x0020 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 -static int tmu_timer_start(void) -{ - ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR); - return 0; -} +#define TMU0_TCR_CALIB 0x0000 -static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload) +static unsigned long tmu_timer_get_offset(void) { - ctrl_outl(interval, TMU0_TCNT); + int count; + static int count_p = 0x7fffffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; /* - * TCNT reloads from TCOR on underflow, clear it if we don't - * intend to auto-reload + * cache volatile jiffies temporarily; we have IRQs turned off. */ - if (reload) - ctrl_outl(interval, TMU0_TCOR); - else - ctrl_outl(0, TMU0_TCOR); + unsigned long jiffies_t; - tmu_timer_start(); -} + /* timer count may underflow right here */ + count = ctrl_inl(TMU0_TCNT); /* read the latched count */ -static int tmu_timer_stop(void) -{ - ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR); - return 0; -} + jiffies_t = jiffies; -static cycle_t tmu_timer_read(void) -{ - return ~ctrl_inl(TMU1_TCNT); -} - -static int tmu_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - tmu0_timer_set_interval(cycles, 1); - return 0; -} + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ -static void tmu_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR); - break; - case CLOCK_EVT_MODE_ONESHOT: - ctrl_outl(0, TMU0_TCOR); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - break; - } + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; } -static struct clock_event_device tmu0_clockevent = { - .name = "tmu0", - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = tmu_set_mode, - .set_next_event = tmu_set_next_event, -}; - static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) { - struct clock_event_device *evt = &tmu0_clockevent; unsigned long timer_status; /* Clear UNF bit */ @@ -102,76 +82,72 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) timer_status &= ~0x100; ctrl_outw(timer_status, TMU0_TCR); - evt->event_handler(evt); + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } -static struct irqaction tmu0_irq = { - .name = "periodic timer", +static struct irqaction tmu_irq = { + .name = "timer", .handler = tmu_timer_interrupt, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .mask = CPU_MASK_NONE, }; -static void tmu0_clk_init(struct clk *clk) +static void tmu_clk_init(struct clk *clk) { - u8 divisor = TMU_TCR_INIT & 0x7; - ctrl_outw(TMU_TCR_INIT, TMU0_TCR); + u8 divisor = TMU0_TCR_INIT & 0x7; + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); clk->rate = clk->parent->rate / (4 << (divisor << 1)); } -static void tmu0_clk_recalc(struct clk *clk) +static void tmu_clk_recalc(struct clk *clk) { u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; clk->rate = clk->parent->rate / (4 << (divisor << 1)); } -static struct clk_ops tmu0_clk_ops = { - .init = tmu0_clk_init, - .recalc = tmu0_clk_recalc, +static struct clk_ops tmu_clk_ops = { + .init = tmu_clk_init, + .recalc = tmu_clk_recalc, }; static struct clk tmu0_clk = { .name = "tmu0_clk", - .ops = &tmu0_clk_ops, + .ops = &tmu_clk_ops, }; -static void tmu1_clk_init(struct clk *clk) +static int tmu_timer_start(void) { - u8 divisor = TMU_TCR_INIT & 0x7; - ctrl_outw(divisor, TMU1_TCR); - clk->rate = clk->parent->rate / (4 << (divisor << 1)); + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + return 0; } -static void tmu1_clk_recalc(struct clk *clk) +static int tmu_timer_stop(void) { - u8 divisor = ctrl_inw(TMU1_TCR) & 0x7; - clk->rate = clk->parent->rate / (4 << (divisor << 1)); + ctrl_outb(0, TMU_TSTR); + return 0; } -static struct clk_ops tmu1_clk_ops = { - .init = tmu1_clk_init, - .recalc = tmu1_clk_recalc, -}; - -static struct clk tmu1_clk = { - .name = "tmu1_clk", - .ops = &tmu1_clk_ops, -}; - static int tmu_timer_init(void) { unsigned long interval; - unsigned long frequency; - setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq); + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); tmu0_clk.parent = clk_get(NULL, "module_clk"); - tmu1_clk.parent = clk_get(NULL, "module_clk"); + /* Start TMU0 */ tmu_timer_stop(); - #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ !defined(CONFIG_CPU_SUBTYPE_SH7785) @@ -179,29 +155,15 @@ static int tmu_timer_init(void) #endif clk_register(&tmu0_clk); - clk_register(&tmu1_clk); clk_enable(&tmu0_clk); - clk_enable(&tmu1_clk); - - frequency = clk_get_rate(&tmu0_clk); - interval = (frequency + HZ / 2) / HZ; - sh_hpt_frequency = clk_get_rate(&tmu1_clk); - ctrl_outl(~0, TMU1_TCNT); - ctrl_outl(~0, TMU1_TCOR); + interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); - tmu0_timer_set_interval(interval, 1); - - tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC, - tmu0_clockevent.shift); - tmu0_clockevent.max_delta_ns = - clockevent_delta2ns(-1, &tmu0_clockevent); - tmu0_clockevent.min_delta_ns = - clockevent_delta2ns(1, &tmu0_clockevent); - - tmu0_clockevent.cpumask = cpumask_of_cpu(0); + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); - clockevents_register_device(&tmu0_clockevent); + tmu_timer_start(); return 0; } @@ -210,7 +172,9 @@ struct sys_timer_ops tmu_timer_ops = { .init = tmu_timer_init, .start = tmu_timer_start, .stop = tmu_timer_stop, - .read = tmu_timer_read, +#ifndef CONFIG_GENERIC_TIME + .get_offset = tmu_timer_get_offset, +#endif }; struct sys_timer tmu_timer = { diff --git a/trunk/arch/sh/kernel/traps.c b/trunk/arch/sh/kernel/traps.c index 3a197649cd83..7b40f0ff3dfc 100644 --- a/trunk/arch/sh/kernel/traps.c +++ b/trunk/arch/sh/kernel/traps.c @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #ifdef CONFIG_SH_KGDB #include @@ -76,6 +76,20 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top) } } +ATOMIC_NOTIFIER_HEAD(shdie_chain); + +int register_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&shdie_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&shdie_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); + static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) @@ -491,7 +505,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) simple: ret = handle_unaligned_ins(instruction,regs); if (ret==0) - regs->pc += instruction_size(instruction); + regs->pc += 2; return ret; } #endif /* CONFIG_CPU_SH2A */ @@ -668,7 +682,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, err = do_fpu_inst(inst, regs); if (!err) { - regs->pc += instruction_size(inst); + regs->pc += 2; return; } /* not a FPU inst. */ diff --git a/trunk/arch/sh/kernel/vsyscall/vsyscall.c b/trunk/arch/sh/kernel/vsyscall/vsyscall.c index e146bafcd14f..7b0f66f03319 100644 --- a/trunk/arch/sh/kernel/vsyscall/vsyscall.c +++ b/trunk/arch/sh/kernel/vsyscall/vsyscall.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/vsyscall/vsyscall.c + * arch/sh/kernel/vsyscall.c * * Copyright (C) 2006 Paul Mundt * diff --git a/trunk/arch/sh/lib/delay.c b/trunk/arch/sh/lib/delay.c index f3ddd2133e6f..351714694d6d 100644 --- a/trunk/arch/sh/lib/delay.c +++ b/trunk/arch/sh/lib/delay.c @@ -24,10 +24,9 @@ inline void __const_udelay(unsigned long xloops) __asm__("dmulu.l %0, %2\n\t" "sts mach, %0" : "=r" (xloops) - : "0" (xloops), - "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) + : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy) : "macl", "mach"); - __delay(xloops); + __delay(xloops * HZ); } void __udelay(unsigned long usecs) diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 253346d7b316..12f3d394dc28 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -218,9 +218,6 @@ endmenu menu "Memory management options" -config QUICKLIST - def_bool y - config MMU bool "Support for memory management hardware" depends on !CPU_SH2 @@ -303,10 +300,6 @@ config NODES_SHIFT config ARCH_FLATMEM_ENABLE def_bool y -config MAX_ACTIVE_REGIONS - int - default "1" - config ARCH_POPULATES_NODE_MAP def_bool y diff --git a/trunk/arch/sh/mm/fault.c b/trunk/arch/sh/mm/fault.c index 9207da67ff8a..0ecc117cade4 100644 --- a/trunk/arch/sh/mm/fault.c +++ b/trunk/arch/sh/mm/fault.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index 8fe223a890ed..4d030988b368 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -67,8 +67,6 @@ void show_mem(void) printk("%d slab pages\n", slab); printk("%d pages shared\n", shared); printk("%d pages swap cached\n", cached); - printk(KERN_INFO "Total of %ld pages in page table cache\n", - quicklist_total_size()); } #ifdef CONFIG_MMU diff --git a/trunk/arch/sparc/kernel/asm-offsets.c b/trunk/arch/sparc/kernel/asm-offsets.c index 6773ed76e414..29d7cfd1c970 100644 --- a/trunk/arch/sparc/kernel/asm-offsets.c +++ b/trunk/arch/sparc/kernel/asm-offsets.c @@ -28,7 +28,7 @@ int foo(void) DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid)); DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid)); DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid)); - /* DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); */ + /* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */ DEFINE(ASIZ_task_uid, sizeof(current->uid)); DEFINE(ASIZ_task_gid, sizeof(current->gid)); DEFINE(ASIZ_task_euid, sizeof(current->euid)); diff --git a/trunk/arch/sparc/kernel/systbls.S b/trunk/arch/sparc/kernel/systbls.S index e3f5b8ed4c52..3a69778c8366 100644 --- a/trunk/arch/sparc/kernel/systbls.S +++ b/trunk/arch/sparc/kernel/systbls.S @@ -80,7 +80,6 @@ sys_call_table: /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .long sys_utimensat #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -197,6 +196,5 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys -/*310*/ .long sunos_nosys #endif diff --git a/trunk/arch/sparc64/kernel/ebus.c b/trunk/arch/sparc64/kernel/ebus.c index ad55a9bb50dd..0ace17bafba4 100644 --- a/trunk/arch/sparc64/kernel/ebus.c +++ b/trunk/arch/sparc64/kernel/ebus.c @@ -13,17 +13,16 @@ #include #include #include -#include #include #include +#include #include #include #include #include #include #include -#include /* EBUS dma library. */ diff --git a/trunk/arch/sparc64/kernel/kprobes.c b/trunk/arch/sparc64/kernel/kprobes.c index c93a15b785fa..a44fe47a3c2b 100644 --- a/trunk/arch/sparc64/kernel/kprobes.c +++ b/trunk/arch/sparc64/kernel/kprobes.c @@ -313,7 +313,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) return 1; } -int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -403,6 +403,15 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobe_handler(args->regs)) ret = NOTIFY_STOP; break; + case DIE_GPF: + 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; } diff --git a/trunk/arch/sparc64/kernel/pci.c b/trunk/arch/sparc64/kernel/pci.c index cf9a75112d0f..966861b212be 100644 --- a/trunk/arch/sparc64/kernel/pci.c +++ b/trunk/arch/sparc64/kernel/pci.c @@ -14,12 +14,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -48,10 +48,10 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, #else /* List of all PCI controllers found in the system. */ -struct pci_pbm_info *pci_pbm_root = NULL; +struct pci_controller_info *pci_controller_root = NULL; -/* Each PBM found gets a unique index. */ -int pci_num_pbms = 0; +/* Each PCI controller found gets a unique index. */ +int pci_num_controllers = 0; volatile int pci_poke_in_progress; volatile int pci_poke_cpu = -1; @@ -291,7 +291,7 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops, /* Find each controller in the system, attach and initialize * software state structure for each and link into the - * pci_pbm_root. Setup the controller enough such + * pci_controller_root. Setup the controller enough such * that bus scanning can be done. */ static void __init pci_controller_probe(void) @@ -377,7 +377,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, const char *type; u32 class; - dev = alloc_pci_dev(); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; @@ -743,6 +743,7 @@ int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) { + struct pci_controller_info *p = pbm->parent; struct device_node *node = pbm->prom_node; struct pci_dev *host_pdev; struct pci_bus *bus; @@ -750,7 +751,7 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) printk("PCI: Scanning PBM %s\n", node->full_name); /* XXX parent device? XXX */ - bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); + bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm); if (!bus) { printk(KERN_ERR "Failed to create bus for %s\n", node->full_name); @@ -775,10 +776,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) static void __init pci_scan_each_controller_bus(void) { - struct pci_pbm_info *pbm; + struct pci_controller_info *p; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) - pbm->scan_bus(pbm); + for (p = pci_controller_root; p; p = p->next) + p->scan_bus(p); } extern void power_init(void); @@ -786,7 +787,7 @@ extern void power_init(void); static int __init pcibios_init(void) { pci_controller_probe(); - if (pci_pbm_root == NULL) + if (pci_controller_root == NULL) return 0; pci_scan_each_controller_bus(); @@ -921,8 +922,10 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc enum pci_mmap_state mmap_state) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; + struct pci_controller_info *p; unsigned long space_size, user_offset, user_size; + p = pbm->parent; if (mmap_state == pci_mmap_io) { space_size = (pbm->io_space.end - pbm->io_space.start) + 1; @@ -1075,7 +1078,11 @@ int pci_domain_nr(struct pci_bus *pbus) if (pbm == NULL || pbm->parent == NULL) { ret = -ENXIO; } else { - ret = pbm->index; + struct pci_controller_info *p = pbm->parent; + + ret = p->index; + ret = ((ret << 1) + + ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); } return ret; @@ -1086,12 +1093,17 @@ EXPORT_SYMBOL(pci_domain_nr); int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - int virt_irq; + struct pci_controller_info *p = pbm->parent; + int virt_irq, err; - if (!pbm->setup_msi_irq) + if (!pbm->msi_num || !p->setup_msi_irq) return -EINVAL; - return pbm->setup_msi_irq(&virt_irq, pdev, desc); + err = p->setup_msi_irq(&virt_irq, pdev, desc); + if (err) + return err; + + return 0; } void arch_teardown_msi_irq(unsigned int virt_irq) @@ -1099,11 +1111,12 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct msi_desc *entry = get_irq_msi(virt_irq); struct pci_dev *pdev = entry->dev; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; + struct pci_controller_info *p = pbm->parent; - if (!pbm->teardown_msi_irq) + if (!pbm->msi_num || !p->setup_msi_irq) return; - return pbm->teardown_msi_irq(virt_irq, pdev); + return p->teardown_msi_irq(virt_irq, pdev); } #endif /* !(CONFIG_PCI_MSI) */ diff --git a/trunk/arch/sparc64/kernel/pci_common.c b/trunk/arch/sparc64/kernel/pci_common.c index f974fefc3ebc..1e6aeedf43c4 100644 --- a/trunk/arch/sparc64/kernel/pci_common.c +++ b/trunk/arch/sparc64/kernel/pci_common.c @@ -9,219 +9,11 @@ #include #include +#include #include #include -#include #include "pci_impl.h" -#include "pci_sun4v.h" - -static int config_out_of_range(struct pci_pbm_info *pbm, - unsigned long bus, - unsigned long devfn, - unsigned long reg) -{ - if (bus < pbm->pci_first_busno || - bus > pbm->pci_last_busno) - return 1; - return 0; -} - -static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm, - unsigned long bus, - unsigned long devfn, - unsigned long reg) -{ - unsigned long rbits = pbm->config_space_reg_bits; - - if (config_out_of_range(pbm, bus, devfn, reg)) - return NULL; - - reg = (reg & ((1 << rbits) - 1)); - devfn <<= rbits; - bus <<= rbits + 8; - - return (void *) (pbm->config_space | bus | devfn | reg); -} - -static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - u16 tmp16; - u8 tmp8; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, - size, value); - - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - - addr = sun4u_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_read8((u8 *)addr, &tmp8); - *value = (u32) tmp8; - break; - - case 2: - if (where & 0x01) { - printk("pci_read_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read16((u16 *)addr, &tmp16); - *value = (u32) tmp16; - break; - - case 4: - if (where & 0x03) { - printk("pci_read_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read32(addr, value); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, - size, value); - addr = sun4u_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_write8((u8 *)addr, value); - break; - - case 2: - if (where & 0x01) { - printk("pci_write_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write16((u16 *)addr, value); - break; - - case 4: - if (where & 0x03) { - printk("pci_write_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write32(addr, value); - } - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops sun4u_pci_ops = { - .read = sun4u_read_pci_cfg, - .write = sun4u_write_pci_cfg, -}; - -static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - u32 devhandle = pbm->devhandle; - unsigned int bus = bus_dev->number; - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - unsigned long ret; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, - size, value); - if (config_out_of_range(pbm, bus, devfn, where)) { - ret = ~0UL; - } else { - ret = pci_sun4v_config_get(devhandle, - HV_PCI_DEVICE_BUILD(bus, device, func), - where, size); - } - switch (size) { - case 1: - *value = ret & 0xff; - break; - case 2: - *value = ret & 0xffff; - break; - case 4: - *value = ret & 0xffffffff; - break; - }; - - - return PCIBIOS_SUCCESSFUL; -} - -static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - u32 devhandle = pbm->devhandle; - unsigned int bus = bus_dev->number; - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - unsigned long ret; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, - size, value); - if (config_out_of_range(pbm, bus, devfn, where)) { - /* Do nothing. */ - } else { - ret = pci_sun4v_config_put(devhandle, - HV_PCI_DEVICE_BUILD(bus, device, func), - where, size, value); - } - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops sun4v_pci_ops = { - .read = sun4v_read_pci_cfg, - .write = sun4v_write_pci_cfg, -}; - -void pci_get_pbm_props(struct pci_pbm_info *pbm) -{ - const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); - - pbm->pci_first_busno = val[0]; - pbm->pci_last_busno = val[1]; - - val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); - if (val) { - pbm->ino_bitmap = (((u64)val[1] << 32UL) | - ((u64)val[0] << 0UL)); - } -} static void pci_register_legacy_regions(struct resource *io_res, struct resource *mem_res) @@ -357,7 +149,8 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) } /* Generic helper routines for PCI error reporting. */ -void pci_scan_for_target_abort(struct pci_pbm_info *pbm, +void pci_scan_for_target_abort(struct pci_controller_info *p, + struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -372,16 +165,18 @@ void pci_scan_for_target_abort(struct pci_pbm_info *pbm, PCI_STATUS_REC_TARGET_ABORT)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("%s: Device %s saw Target Abort [%016x]\n", - pbm->name, pci_name(pdev), status); + printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n", + p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), + pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_target_abort(pbm, bus); + pci_scan_for_target_abort(p, pbm, bus); } -void pci_scan_for_master_abort(struct pci_pbm_info *pbm, +void pci_scan_for_master_abort(struct pci_controller_info *p, + struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -395,16 +190,18 @@ void pci_scan_for_master_abort(struct pci_pbm_info *pbm, (status & (PCI_STATUS_REC_MASTER_ABORT)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("%s: Device %s received Master Abort [%016x]\n", - pbm->name, pci_name(pdev), status); + printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n", + p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), + pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_master_abort(pbm, bus); + pci_scan_for_master_abort(p, pbm, bus); } -void pci_scan_for_parity_error(struct pci_pbm_info *pbm, +void pci_scan_for_parity_error(struct pci_controller_info *p, + struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -419,11 +216,12 @@ void pci_scan_for_parity_error(struct pci_pbm_info *pbm, PCI_STATUS_DETECTED_PARITY)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("%s: Device %s saw Parity Error [%016x]\n", - pbm->name, pci_name(pdev), status); + printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n", + p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), + pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_parity_error(pbm, bus); + pci_scan_for_parity_error(p, pbm, bus); } diff --git a/trunk/arch/sparc64/kernel/pci_fire.c b/trunk/arch/sparc64/kernel/pci_fire.c index 9198c1a0f7a5..0fe626631e12 100644 --- a/trunk/arch/sparc64/kernel/pci_fire.c +++ b/trunk/arch/sparc64/kernel/pci_fire.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -27,9 +28,153 @@ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory") -static void pci_fire_scan_bus(struct pci_pbm_info *pbm) +/* Fire config space address format is nearly identical to + * that of SCHIZO and PSYCHO, except that in order to accomodate + * PCI-E extended config space the encoding can handle 12 bits + * of register address: + * + * 32 28 27 20 19 15 14 12 11 2 1 0 + * ------------------------------------------------- + * |0 0 0 0 0| bus | device | function | reg | 0 0 | + * ------------------------------------------------- + */ +#define FIRE_CONFIG_BASE(PBM) ((PBM)->config_space) +#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ + (((unsigned long)(BUS) << 20) | \ + ((unsigned long)(DEVFN) << 12) | \ + ((unsigned long)(REG))) + +static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned int devfn, + int where) +{ + if (!pbm) + return NULL; + return (void *) + (FIRE_CONFIG_BASE(pbm) | + FIRE_CONFIG_ENCODE(bus, devfn, where)); +} + +/* FIRE PCI configuration space accessors. */ + +static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_fire_ops = { + .read = fire_read_pci_cfg, + .write = fire_write_pci_cfg, +}; + +static void pbm_scan_bus(struct pci_controller_info *p, + struct pci_pbm_info *pbm) { pbm->pci_bus = pci_scan_one_pbm(pbm); +} + +static void pci_fire_scan_bus(struct pci_controller_info *p) +{ + struct device_node *dp; + + if ((dp = p->pbm_A.prom_node) != NULL) + pbm_scan_bus(p, &p->pbm_A); + + if ((dp = p->pbm_B.prom_node) != NULL) + pbm_scan_bus(p, &p->pbm_B); /* XXX register error interrupt handlers XXX */ } @@ -168,25 +313,18 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) } static void pci_fire_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid) + struct device_node *dp, u32 portid) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; + const u32 *ino_bitmap; + const unsigned int *busrange; if ((portid & 1) == 0) pbm = &p->pbm_A; else pbm = &p->pbm_B; - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->scan_bus = pci_fire_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 12; - - pbm->index = pci_num_pbms++; - pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -200,7 +338,13 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - pci_get_pbm_props(pbm); + ino_bitmap = of_get_property(dp, "ino-bitmap", NULL); + pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | + ((u64)ino_bitmap[0] << 0UL)); + + busrange = of_get_property(dp, "bus-range", NULL); + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; pci_fire_hw_init(pbm); pci_fire_pbm_iommu_init(pbm); @@ -218,11 +362,19 @@ void fire_pci_init(struct device_node *dp, const char *model_name) struct pci_controller_info *p; u32 portid = of_getintprop_default(dp, "portid", 0xff); struct iommu *iommu; - struct pci_pbm_info *pbm; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + for (p = pci_controller_root; p; p = p->next) { + struct pci_pbm_info *pbm; + + if (p->pbm_A.prom_node && p->pbm_B.prom_node) + continue; + + pbm = (p->pbm_A.prom_node ? + &p->pbm_A : + &p->pbm_B); + if (portid_compare(pbm->portid, portid)) { - pci_fire_pbm_init(pbm->parent, dp, portid); + pci_fire_pbm_init(p, dp, portid); return; } } @@ -243,7 +395,14 @@ void fire_pci_init(struct device_node *dp, const char *model_name) p->pbm_B.iommu = iommu; + p->next = pci_controller_root; + pci_controller_root = p; + + p->index = pci_num_controllers++; + + p->scan_bus = pci_fire_scan_bus; /* XXX MSI support XXX */ + p->pci_ops = &pci_fire_ops; /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. diff --git a/trunk/arch/sparc64/kernel/pci_impl.h b/trunk/arch/sparc64/kernel/pci_impl.h index f660c2b685eb..1208583fcb83 100644 --- a/trunk/arch/sparc64/kernel/pci_impl.h +++ b/trunk/arch/sparc64/kernel/pci_impl.h @@ -8,132 +8,15 @@ #include #include -#include -#include #include #include -#include -/* The abstraction used here is that there are PCI controllers, - * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules - * underneath. Each PCI bus module uses an IOMMU (shared by both - * PBMs of a controller, or per-PBM), and if a streaming buffer - * is present, each PCI bus module has it's own. (ie. the IOMMU - * might be shared between PBMs, the STC is never shared) - * Furthermore, each PCI bus module controls it's own autonomous - * PCI bus. - */ - -#define PCI_STC_FLUSHFLAG_INIT(STC) \ - (*((STC)->strbuf_flushflag) = 0UL) -#define PCI_STC_FLUSHFLAG_SET(STC) \ - (*((STC)->strbuf_flushflag) != 0UL) - -struct pci_controller_info; - -struct pci_pbm_info { - struct pci_pbm_info *next; - int index; - - /* PCI controller we sit under. */ - struct pci_controller_info *parent; - - /* Physical address base of controller registers. */ - unsigned long controller_regs; - - /* Physical address base of PBM registers. */ - unsigned long pbm_regs; - - /* Physical address of DMA sync register, if any. */ - unsigned long sync_reg; - - /* Opaque 32-bit system bus Port ID. */ - u32 portid; - - /* Opaque 32-bit handle used for hypervisor calls. */ - u32 devhandle; - - /* Chipset version information. */ - int chip_type; -#define PBM_CHIP_TYPE_SABRE 1 -#define PBM_CHIP_TYPE_PSYCHO 2 -#define PBM_CHIP_TYPE_SCHIZO 3 -#define PBM_CHIP_TYPE_SCHIZO_PLUS 4 -#define PBM_CHIP_TYPE_TOMATILLO 5 - int chip_version; - int chip_revision; - - /* Name used for top-level resources. */ - char *name; - - /* OBP specific information. */ - struct device_node *prom_node; - u64 ino_bitmap; - - /* PBM I/O and Memory space resources. */ - struct resource io_space; - struct resource mem_space; - - /* Base of PCI Config space, can be per-PBM or shared. */ - unsigned long config_space; - - /* This will be 12 on PCI-E controllers, 8 elsewhere. */ - unsigned long config_space_reg_bits; - - /* State of 66MHz capabilities on this PBM. */ - int is_66mhz_capable; - int all_devs_66mhz; - -#ifdef CONFIG_PCI_MSI - /* MSI info. */ - u32 msiq_num; - u32 msiq_ent_count; - u32 msiq_first; - u32 msiq_first_devino; - u32 msi_num; - u32 msi_first; - u32 msi_data_mask; - u32 msix_data_width; - u64 msi32_start; - u64 msi64_start; - u32 msi32_len; - u32 msi64_len; - void *msi_queues; - unsigned long *msi_bitmap; - int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, - struct msi_desc *entry); - void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); -#endif /* !(CONFIG_PCI_MSI) */ - - /* This PBM's streaming buffer. */ - struct strbuf stc; - - /* IOMMU state, potentially shared by both PBM segments. */ - struct iommu *iommu; - - /* Now things for the actual PCI bus probes. */ - unsigned int pci_first_busno; - unsigned int pci_last_busno; - struct pci_bus *pci_bus; - void (*scan_bus)(struct pci_pbm_info *); - struct pci_ops *pci_ops; -}; - -struct pci_controller_info { - /* The PCI bus modules controlled by us. */ - struct pci_pbm_info pbm_A; - struct pci_pbm_info pbm_B; -}; - -extern struct pci_pbm_info *pci_pbm_root; +extern struct pci_controller_info *pci_controller_root; extern unsigned long pci_memspace_mask; -extern int pci_num_pbms; +extern int pci_num_controllers; /* PCI bus scanning and fixup support. */ -extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, - u32 dma_offset, u32 dma_addr_mask); -extern void pci_get_pbm_props(struct pci_pbm_info *pbm); extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); @@ -147,9 +30,9 @@ extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, u32 value); /* Error reporting support. */ -extern void pci_scan_for_target_abort(struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_master_abort(struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_parity_error(struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); /* Configuration space access. */ extern void pci_config_read8(u8 *addr, u8 *ret); @@ -159,7 +42,4 @@ extern void pci_config_write8(u8 *addr, u8 val); extern void pci_config_write16(u16 *addr, u16 val); extern void pci_config_write32(u32 *addr, u32 val); -extern struct pci_ops sun4u_pci_ops; -extern struct pci_ops sun4v_pci_ops; - #endif /* !(PCI_IMPL_H) */ diff --git a/trunk/arch/sparc64/kernel/pci_iommu.c b/trunk/arch/sparc64/kernel/pci_iommu.c index dfd6f9f4790b..9e405cbbcb0d 100644 --- a/trunk/arch/sparc64/kernel/pci_iommu.c +++ b/trunk/arch/sparc64/kernel/pci_iommu.c @@ -8,12 +8,10 @@ #include #include #include -#include -#include +#include #include "iommu_common.h" -#include "pci_impl.h" #define PCI_STC_CTXMATCH_ADDR(STC, CTX) \ ((STC)->strbuf_ctxmatch_base + ((CTX) << 3)) diff --git a/trunk/arch/sparc64/kernel/pci_psycho.c b/trunk/arch/sparc64/kernel/pci_psycho.c index 598393a2df16..253d40ec2245 100644 --- a/trunk/arch/sparc64/kernel/pci_psycho.c +++ b/trunk/arch/sparc64/kernel/pci_psycho.c @@ -12,12 +12,12 @@ #include #include +#include #include #include #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -94,6 +94,127 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, PSYCHO_CONFIG_ENCODE(bus, devfn, where)); } +static int psycho_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + return ((pbm->parent == 0) || + ((pbm == &pbm->parent->pbm_B) && + (bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8) || + ((pbm == &pbm->parent->pbm_A) && + (bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8)); +} + +/* PSYCHO PCI configuration space accessors. */ + +static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (psycho_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = (u32) tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = (u32) tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (psycho_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops psycho_ops = { + .read = psycho_read_pci_cfg, + .write = psycho_write_pci_cfg, +}; + /* PSYCHO error handling support. */ enum psycho_error_type { UE_ERR, CE_ERR, PCI_ERR @@ -144,11 +265,12 @@ static unsigned long stc_error_buf[128]; static unsigned long stc_tag_buf[16]; static unsigned long stc_line_buf[16]; -static void __psycho_check_one_stc(struct pci_pbm_info *pbm, +static void __psycho_check_one_stc(struct pci_controller_info *p, + struct pci_pbm_info *pbm, int is_pbm_a) { struct strbuf *strbuf = &pbm->stc; - unsigned long regbase = pbm->controller_regs; + unsigned long regbase = p->pbm_A.controller_regs; unsigned long err_base, tag_base, line_base; u64 control; int i; @@ -204,8 +326,9 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, unsigned long errval = stc_error_buf[j]; if (errval != 0) { saw_error++; - printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", - pbm->name, + printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n", + p->index, + (is_pbm_a ? 'A' : 'B'), j, (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, (errval & PSYCHO_STCERR_READ) ? 1 : 0); @@ -214,16 +337,18 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, if (saw_error != 0) { unsigned long tagval = stc_tag_buf[i]; unsigned long lineval = stc_line_buf[i]; - printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", - pbm->name, + printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", + p->index, + (is_pbm_a ? 'A' : 'B'), i, ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), (tagval & PSYCHO_STCTAG_VPN), ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); - printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" + printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" "V(%d)FOFN(%d)]\n", - pbm->name, + p->index, + (is_pbm_a ? 'A' : 'B'), i, ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), @@ -237,13 +362,20 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, spin_unlock(&stc_buf_lock); } -static void __psycho_check_stc_error(struct pci_pbm_info *pbm, +static void __psycho_check_stc_error(struct pci_controller_info *p, unsigned long afsr, unsigned long afar, enum psycho_error_type type) { - __psycho_check_one_stc(pbm, - (pbm == &pbm->parent->pbm_A)); + struct pci_pbm_info *pbm; + + pbm = &p->pbm_A; + if (pbm->stc.strbuf_enabled) + __psycho_check_one_stc(p, pbm, 1); + + pbm = &p->pbm_B; + if (pbm->stc.strbuf_enabled) + __psycho_check_one_stc(p, pbm, 0); } /* When an Uncorrectable Error or a PCI Error happens, we @@ -281,12 +413,12 @@ static void __psycho_check_stc_error(struct pci_pbm_info *pbm, #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL -static void psycho_check_iommu_error(struct pci_pbm_info *pbm, +static void psycho_check_iommu_error(struct pci_controller_info *p, unsigned long afsr, unsigned long afar, enum psycho_error_type type) { - struct iommu *iommu = pbm->iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -317,8 +449,8 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, type_string = "ECC Error"; break; }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); + printk("PSYCHO%d: IOMMU Error, type[%s]\n", + p->index, type_string); /* Put the IOMMU into diagnostic mode and probe * it's TLB for entries with error status. @@ -333,7 +465,7 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, psycho_write(iommu->iommu_control, control | PSYCHO_IOMMU_CTRL_DENAB); for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; + unsigned long base = p->pbm_A.controller_regs; iommu_tag[i] = psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); @@ -371,20 +503,20 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, type_string = "ECC Error"; break; }; - printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", - pbm->name, i, type_string, + printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", + p->index, i, type_string, ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - pbm->name, i, + printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", + p->index, i, ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } - __psycho_check_stc_error(pbm, afsr, afar, type); + __psycho_check_stc_error(p, afsr, afar, type); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -409,10 +541,9 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, static irqreturn_t psycho_ue_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; - unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; - unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR; + unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -429,22 +560,22 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Uncorrectable Error, primary error type[%s]\n", - pbm->name, + printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n", + p->index, (((error_bits & PSYCHO_UEAFSR_PPIO) ? "PIO" : ((error_bits & PSYCHO_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & PSYCHO_UEAFSR_PDWR) ? "DMA Write" : "???"))))); - printk("%s: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n", - pbm->name, + printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n", + p->index, (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL, (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL, (afsr & PSYCHO_UEAFSR_MID) >> 24UL, ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0)); - printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: UE Secondary errors [", pbm->name); + printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar); + printk("PSYCHO%d: UE Secondary errors [", p->index); reported = 0; if (afsr & PSYCHO_UEAFSR_SPIO) { reported++; @@ -462,9 +593,8 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) printk("(none)"); printk("]\n"); - /* Interrogate both IOMMUs for error status. */ - psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); - psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); + /* Interrogate IOMMU for error status. */ + psycho_check_iommu_error(p, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -488,9 +618,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) static irqreturn_t psycho_ce_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg = pbm->controller_regs + PSYCHO_CE_AFSR; - unsigned long afar_reg = pbm->controller_regs + PSYCHO_CE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR; + unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -507,8 +637,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Correctable Error, primary error type[%s]\n", - pbm->name, + printk("PSYCHO%d: Correctable Error, primary error type[%s]\n", + p->index, (((error_bits & PSYCHO_CEAFSR_PPIO) ? "PIO" : ((error_bits & PSYCHO_CEAFSR_PDRD) ? @@ -519,16 +649,16 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " + printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "UPA_MID[%02lx] was_block(%d)\n", - pbm->name, + p->index, (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL, (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL, (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL, (afsr & PSYCHO_CEAFSR_MID) >> 24UL, ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0)); - printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: CE Secondary errors [", pbm->name); + printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar); + printk("PSYCHO%d: CE Secondary errors [", p->index); reported = 0; if (afsr & PSYCHO_CEAFSR_SPIO) { reported++; @@ -643,8 +773,8 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, + printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n", + p->index, (is_pbm_a ? 'A' : 'B'), (((error_bits & PSYCHO_PCIAFSR_PMA) ? "Master Abort" : ((error_bits & PSYCHO_PCIAFSR_PTA) ? @@ -653,13 +783,15 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) "Excessive Retries" : ((error_bits & PSYCHO_PCIAFSR_PPERR) ? "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", - pbm->name, + printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", + p->index, (is_pbm_a ? 'A' : 'B'), (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); + printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n", + p->index, (is_pbm_a ? 'A' : 'B'), afar); + printk("PSYCHO%d(PBM%c): PCI Secondary errors [", + p->index, (is_pbm_a ? 'A' : 'B')); reported = 0; if (afsr & PSYCHO_PCIAFSR_SMA) { reported++; @@ -691,11 +823,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { - psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(pbm, pbm->pci_bus); + psycho_check_iommu_error(p, afsr, afar, PCI_ERR); + pci_scan_for_target_abort(p, pbm, pbm->pci_bus); } if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); + pci_scan_for_master_abort(p, pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive @@ -705,7 +837,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); + pci_scan_for_parity_error(p, pbm, pbm->pci_bus); return IRQ_HANDLED; } @@ -715,49 +847,34 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ #define PSYCHO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ -static void psycho_register_error_handlers(struct pci_pbm_info *pbm) +static void psycho_register_error_handlers(struct pci_controller_info *p) { + struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct of_device *op = of_find_device_by_node(pbm->prom_node); - unsigned long base = pbm->controller_regs; + unsigned long base = p->pbm_A.controller_regs; u64 tmp; - int err; if (!op) return; /* Psycho interrupt property order is: - * 0: PCIERR INO for this PBM + * 0: PCIERR PBM B INO * 1: UE ERR * 2: CE ERR * 3: POWER FAIL * 4: SPARE HARDWARE - * 5: POWER MANAGEMENT + * 5: PCIERR PBM A INO */ if (op->num_irqs < 6) return; - /* We really mean to ignore the return result here. Two - * PCI controller share the same interrupt numbers and - * drive the same front-end hardware. Whichever of the - * two get in here first will register the IRQ handler - * the second will just error out since we do not pass in - * IRQF_SHARED. - */ - err = request_irq(op->irqs[1], psycho_ue_intr, 0, - "PSYCHO_UE", pbm); - err = request_irq(op->irqs[2], psycho_ce_intr, 0, - "PSYCHO_CE", pbm); - - /* This one, however, ought not to fail. We can just warn - * about it since the system can still operate properly even - * if this fails. - */ - err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, - "PSYCHO_PCIERR", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register PCIERR, " - "err=%d\n", pbm->name, err); + request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO UE", p); + request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO CE", p); + request_irq(op->irqs[5], psycho_pcierr_intr, IRQF_SHARED, + "PSYCHO PCIERR-A", &p->pbm_A); + request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, + "PSYCHO PCIERR-B", &p->pbm_B); /* Enable UE and CE interrupts for controller. */ psycho_write(base + PSYCHO_ECC_CTRL, @@ -801,45 +918,54 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void psycho_scan_bus(struct pci_pbm_info *pbm) +static void pbm_scan_bus(struct pci_controller_info *p, + struct pci_pbm_info *pbm) { - pbm_config_busmastering(pbm); - pbm->is_66mhz_capable = 0; pbm->pci_bus = pci_scan_one_pbm(pbm); +} + +static void psycho_scan_bus(struct pci_controller_info *p) +{ + pbm_config_busmastering(&p->pbm_B); + p->pbm_B.is_66mhz_capable = 0; + pbm_config_busmastering(&p->pbm_A); + p->pbm_A.is_66mhz_capable = 1; + pbm_scan_bus(p, &p->pbm_B); + pbm_scan_bus(p, &p->pbm_A); /* After the PCI bus scan is complete, we can register * the error interrupt handlers. */ - psycho_register_error_handlers(pbm); + psycho_register_error_handlers(p); } -static void psycho_iommu_init(struct pci_pbm_info *pbm) +static void psycho_iommu_init(struct pci_controller_info *p) { - struct iommu *iommu = pbm->iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long i; u64 control; /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; + iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; + iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; + iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH; /* PSYCHO's IOMMU lacks ctx flushing. */ iommu->iommu_ctxflush = 0; /* We use the main control register of PSYCHO as the write * completion register. */ - iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; + iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL; /* * Invalidate TLB Entries. */ - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); + control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); control |= PSYCHO_IOMMU_CTRL_DENAB; - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); for(i = 0; i < 16; i++) { - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); } /* Leave diag mode enabled for full-flushing done @@ -847,17 +973,17 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm) */ pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(iommu->page_table)); - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); + control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); /* If necessary, hook us up for starfire IRQ translations. */ if (this_is_starfire) - starfire_hookup(pbm->portid); + starfire_hookup(p->pbm_A.portid); } #define PSYCHO_IRQ_RETRY 0x1a00UL @@ -872,35 +998,36 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm) #define PSYCHO_PCIDIAG_IPAPAR 0x0000000000000002UL /* Invert PIO address parity */ #define PSYCHO_PCIDIAG_LPBACK 0x0000000000000001UL /* Enable loopback mode */ -static void psycho_controller_hwinit(struct pci_pbm_info *pbm) +static void psycho_controller_hwinit(struct pci_controller_info *p) { u64 tmp; - psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5); /* Enable arbiter for all PCI slots. */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); + tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); + psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); + tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); + psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp); /* Disable DMA write / PIO read synchronization on * both PCI bus segments. * [ U2P Erratum 1243770, STP2223BGA data sheet ] */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); + tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); + psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); + tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); + psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); } -static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, +static void psycho_pbm_strbuf_init(struct pci_controller_info *p, + struct pci_pbm_info *pbm, int is_pbm_a) { unsigned long base = pbm->controller_regs; @@ -961,6 +1088,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, static void psycho_pbm_init(struct pci_controller_info *p, struct device_node *dp, int is_pbm_a) { + unsigned int *busrange; struct property *prop; struct pci_pbm_info *pbm; @@ -969,15 +1097,6 @@ static void psycho_pbm_init(struct pci_controller_info *p, else pbm = &p->pbm_B; - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->scan_bus = psycho_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_version = 0; prop = of_find_property(dp, "version#", NULL); @@ -998,9 +1117,12 @@ static void psycho_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - pci_get_pbm_props(pbm); + prop = of_find_property(dp, "bus-range", NULL); + busrange = prop->value; + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; - psycho_pbm_strbuf_init(pbm, is_pbm_a); + psycho_pbm_strbuf_init(p, pbm, is_pbm_a); } #define PSYCHO_CONFIGSPACE 0x001000000UL @@ -1009,7 +1131,6 @@ void psycho_init(struct device_node *dp, char *model_name) { struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; - struct pci_pbm_info *pbm; struct iommu *iommu; struct property *prop; u32 upa_portid; @@ -1020,9 +1141,7 @@ void psycho_init(struct device_node *dp, char *model_name) if (prop) upa_portid = *(u32 *) prop->value; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - struct pci_controller_info *p = pbm->parent; - + for(p = pci_controller_root; p; p = p->next) { if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); psycho_pbm_init(p, dp, is_pbm_a); @@ -1042,8 +1161,14 @@ void psycho_init(struct device_node *dp, char *model_name) } p->pbm_A.iommu = p->pbm_B.iommu = iommu; + p->next = pci_controller_root; + pci_controller_root = p; + p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; + p->index = pci_num_controllers++; + p->scan_bus = psycho_scan_bus; + p->pci_ops = &psycho_ops; prop = of_find_property(dp, "reg", NULL); pr_regs = prop->value; @@ -1060,9 +1185,9 @@ void psycho_init(struct device_node *dp, char *model_name) */ pci_memspace_mask = 0x7fffffffUL; - psycho_controller_hwinit(&p->pbm_A); + psycho_controller_hwinit(p); - psycho_iommu_init(&p->pbm_A); + psycho_iommu_init(p); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); psycho_pbm_init(p, dp, is_pbm_a); diff --git a/trunk/arch/sparc64/kernel/pci_sabre.c b/trunk/arch/sparc64/kernel/pci_sabre.c index e2377796de89..397862fbd9e1 100644 --- a/trunk/arch/sparc64/kernel/pci_sabre.c +++ b/trunk/arch/sparc64/kernel/pci_sabre.c @@ -13,12 +13,12 @@ #include #include +#include #include #include #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -205,15 +205,300 @@ #define SABRE_MEMSPACE 0x100000000UL #define SABRE_MEMSPACE_SIZE 0x07fffffffUL +/* UltraSparc-IIi Programmer's Manual, page 325, PCI + * configuration space address format: + * + * 32 24 23 16 15 11 10 8 7 2 1 0 + * --------------------------------------------------------- + * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | + * --------------------------------------------------------- + */ +#define SABRE_CONFIG_BASE(PBM) \ + ((PBM)->config_space | (1UL << 24)) +#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ + (((unsigned long)(BUS) << 16) | \ + ((unsigned long)(DEVFN) << 8) | \ + ((unsigned long)(REG))) + static int hummingbird_p; static struct pci_bus *sabre_root_bus; +static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned int devfn, + int where) +{ + if (!pbm) + return NULL; + return (void *) + (SABRE_CONFIG_BASE(pbm) | + SABRE_CONFIG_ENCODE(bus, devfn, where)); +} + +static int sabre_out_of_range(unsigned char devfn) +{ + if (hummingbird_p) + return 0; + + return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || + ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || + (PCI_SLOT(devfn) > 1)); +} + +static int __sabre_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + if (hummingbird_p) + return 0; + + return ((pbm->parent == 0) || + ((pbm == &pbm->parent->pbm_A) && + (bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8)); +} + +static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (__sabre_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_read8((u8 *) addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *) addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus, devfn, where, + size, value); + + if (!bus->number && sabre_out_of_range(devfn)) { + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + return PCIBIOS_SUCCESSFUL; + } + + if (bus->number || PCI_SLOT(devfn)) + return __sabre_read_pci_cfg(bus, devfn, where, size, value); + + /* When accessing PCI config space of the PCI controller itself (bus + * 0, device slot 0, function 0) there are restrictions. Each + * register must be accessed as it's natural size. Thus, for example + * the Vendor ID must be accessed as a 16-bit quantity. + */ + + switch (size) { + case 1: + if (where < 8) { + u32 tmp32; + u16 tmp16; + + __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); + tmp16 = (u16) tmp32; + if (where & 1) + *value = tmp16 >> 8; + else + *value = tmp16 & 0xff; + } else + return __sabre_read_pci_cfg(bus, devfn, where, 1, value); + break; + + case 2: + if (where < 8) + return __sabre_read_pci_cfg(bus, devfn, where, 2, value); + else { + u32 tmp32; + u8 tmp8; + + __sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32); + tmp8 = (u8) tmp32; + *value = tmp8; + __sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32); + tmp8 = (u8) tmp32; + *value |= tmp8 << 8; + } + break; + + case 4: { + u32 tmp32; + u16 tmp16; + + sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32); + tmp16 = (u16) tmp32; + *value = tmp16; + sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32); + tmp16 = (u16) tmp32; + *value |= tmp16 << 16; + break; + } + } + return PCIBIOS_SUCCESSFUL; +} + +static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (__sabre_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *) addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *) addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write32(addr, value); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus, devfn, where, + size, value); + + if (bus->number) + return __sabre_write_pci_cfg(bus, devfn, where, size, value); + + if (sabre_out_of_range(devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + if (where < 8) { + u32 tmp32; + u16 tmp16; + + __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); + tmp16 = (u16) tmp32; + if (where & 1) { + value &= 0x00ff; + value |= tmp16 << 8; + } else { + value &= 0xff00; + value |= tmp16; + } + tmp32 = (u32) tmp16; + return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32); + } else + return __sabre_write_pci_cfg(bus, devfn, where, 1, value); + break; + case 2: + if (where < 8) + return __sabre_write_pci_cfg(bus, devfn, where, 2, value); + else { + __sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff); + __sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8); + } + break; + case 4: + sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff); + sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops sabre_ops = { + .read = sabre_read_pci_cfg, + .write = sabre_write_pci_cfg, +}; + /* SABRE error handling support. */ -static void sabre_check_iommu_error(struct pci_pbm_info *pbm, +static void sabre_check_iommu_error(struct pci_controller_info *p, unsigned long afsr, unsigned long afar) { - struct iommu *iommu = pbm->iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -241,8 +526,8 @@ static void sabre_check_iommu_error(struct pci_pbm_info *pbm, type_string = "Unknown"; break; }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); + printk("SABRE%d: IOMMU Error, type[%s]\n", + p->index, type_string); /* Enter diagnostic mode and probe for error'd * entries in the IOTLB. @@ -251,7 +536,7 @@ static void sabre_check_iommu_error(struct pci_pbm_info *pbm, sabre_write(iommu->iommu_control, (control | SABRE_IOMMUCTRL_DENAB)); for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; + unsigned long base = p->pbm_A.controller_regs; iommu_tag[i] = sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); @@ -281,13 +566,13 @@ static void sabre_check_iommu_error(struct pci_pbm_info *pbm, type_string = "Unknown"; break; }; - printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - pbm->name, i, tag, type_string, + printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", + p->index, i, tag, type_string, ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); - printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - pbm->name, i, data, + printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", + p->index, i, data, ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), @@ -299,9 +584,9 @@ static void sabre_check_iommu_error(struct pci_pbm_info *pbm, static irqreturn_t sabre_ue_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg = pbm->controller_regs + SABRE_UE_AFSR; - unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR; + unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -319,21 +604,21 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Uncorrectable Error, primary error type[%s%s]\n", - pbm->name, + printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n", + p->index, ((error_bits & SABRE_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & SABRE_UEAFSR_PDWR) ? "DMA Write" : "???")), ((error_bits & SABRE_UEAFSR_PDTE) ? ":Translation Error" : "")); - printk("%s: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", - pbm->name, + printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", + p->index, (afsr & SABRE_UEAFSR_BMSK) >> 32UL, (afsr & SABRE_UEAFSR_OFF) >> 29UL, ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0)); - printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: UE Secondary errors [", pbm->name); + printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar); + printk("SABRE%d: UE Secondary errors [", p->index); reported = 0; if (afsr & SABRE_UEAFSR_SDRD) { reported++; @@ -352,16 +637,16 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - sabre_check_iommu_error(pbm, afsr, afar); + sabre_check_iommu_error(p, afsr, afar); return IRQ_HANDLED; } static irqreturn_t sabre_ce_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg = pbm->controller_regs + SABRE_CE_AFSR; - unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR; + unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -378,8 +663,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Correctable Error, primary error type[%s]\n", - pbm->name, + printk("SABRE%d: Correctable Error, primary error type[%s]\n", + p->index, ((error_bits & SABRE_CEAFSR_PDRD) ? "DMA Read" : ((error_bits & SABRE_CEAFSR_PDWR) ? @@ -388,15 +673,15 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " + printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "was_block(%d)\n", - pbm->name, + p->index, (afsr & SABRE_CEAFSR_ESYND) >> 48UL, (afsr & SABRE_CEAFSR_BMSK) >> 32UL, (afsr & SABRE_CEAFSR_OFF) >> 29UL, ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0)); - printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: CE Secondary errors [", pbm->name); + printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar); + printk("SABRE%d: CE Secondary errors [", p->index); reported = 0; if (afsr & SABRE_CEAFSR_SDRD) { reported++; @@ -413,13 +698,13 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) +static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) { unsigned long csr_reg, csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; u16 stat; - csr_reg = pbm->controller_regs + SABRE_PCICTRL; + csr_reg = p->pbm_A.controller_regs + SABRE_PCICTRL; csr = sabre_read(csr_reg); csr_error_bits = csr & SABRE_PCICTRL_SERR; @@ -429,8 +714,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) /* Log 'em. */ if (csr_error_bits & SABRE_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", - pbm->name); + printk("SABRE%d: PCI SERR signal asserted.\n", + p->index); ret = IRQ_HANDLED; } pci_bus_read_config_word(sabre_root_bus, 0, @@ -440,8 +725,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); + printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", + p->index, stat); pci_bus_write_config_word(sabre_root_bus, 0, PCI_STATUS, 0xffff); ret = IRQ_HANDLED; @@ -451,13 +736,13 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; + struct pci_controller_info *p = dev_id; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; int reported; - afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; - afar_reg = pbm->controller_regs + SABRE_PIOAFAR; + afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR; + afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR; /* Latch error status. */ afar = sabre_read(afar_reg); @@ -470,12 +755,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); if (!error_bits) - return sabre_pcierr_intr_other(pbm); + return sabre_pcierr_intr_other(p); sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, + printk("SABRE%d: PCI Error, primary error type[%s]\n", + p->index, (((error_bits & SABRE_PIOAFSR_PMA) ? "Master Abort" : ((error_bits & SABRE_PIOAFSR_PTA) ? @@ -484,12 +769,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) "Excessive Retries" : ((error_bits & SABRE_PIOAFSR_PPERR) ? "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] was_block(%d)\n", - pbm->name, + printk("SABRE%d: bytemask[%04lx] was_block(%d)\n", + p->index, (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); + printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar); + printk("SABRE%d: PCI Secondary errors [", p->index); reported = 0; if (afsr & SABRE_PIOAFSR_SMA) { reported++; @@ -521,11 +806,11 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { - sabre_check_iommu_error(pbm, afsr, afar); - pci_scan_for_target_abort(pbm, pbm->pci_bus); + sabre_check_iommu_error(p, afsr, afar); + pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); } if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); + pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); /* For excessive retries, SABRE/PBM will abort the device * and there is no way to specifically check for excessive @@ -535,18 +820,18 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); + pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); return IRQ_HANDLED; } -static void sabre_register_error_handlers(struct pci_pbm_info *pbm) +static void sabre_register_error_handlers(struct pci_controller_info *p) { + struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct device_node *dp = pbm->prom_node; struct of_device *op; unsigned long base = pbm->controller_regs; u64 tmp; - int err; if (pbm->chip_type == PBM_CHIP_TYPE_SABRE) dp = dp->parent; @@ -573,31 +858,22 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); - if (err) - printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", - pbm->name, err); + request_irq(op->irqs[1], sabre_ue_intr, IRQF_SHARED, "SABRE UE", p); sabre_write(base + SABRE_CE_AFSR, (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); - err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); - if (err) - printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", - pbm->name, err); - err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, - "SABRE_PCIERR", pbm); - if (err) - printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", - pbm->name, err); + request_irq(op->irqs[2], sabre_ce_intr, IRQF_SHARED, "SABRE CE", p); + request_irq(op->irqs[0], sabre_pcierr_intr, IRQF_SHARED, + "SABRE PCIERR", p); tmp = sabre_read(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; sabre_write(base + SABRE_PCICTRL, tmp); } -static void apb_init(struct pci_bus *sabre_bus) +static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) { struct pci_dev *pdev; @@ -633,7 +909,7 @@ static void apb_init(struct pci_bus *sabre_bus) } } -static void sabre_scan_bus(struct pci_pbm_info *pbm) +static void sabre_scan_bus(struct pci_controller_info *p) { static int once; struct pci_bus *pbus; @@ -642,7 +918,7 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm) * at 66Mhz, but the front side of APB runs at 33Mhz * for both segments. */ - pbm->is_66mhz_capable = 0; + p->pbm_A.is_66mhz_capable = 0; /* This driver has not been verified to handle * multiple SABREs yet, so trap this. @@ -656,41 +932,41 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm) } once++; - pbus = pci_scan_one_pbm(pbm); + pbus = pci_scan_one_pbm(&p->pbm_A); if (!pbus) return; sabre_root_bus = pbus; - apb_init(pbus); + apb_init(p, pbus); - sabre_register_error_handlers(pbm); + sabre_register_error_handlers(p); } -static void sabre_iommu_init(struct pci_pbm_info *pbm, +static void sabre_iommu_init(struct pci_controller_info *p, int tsbsize, unsigned long dvma_offset, u32 dma_mask) { - struct iommu *iommu = pbm->iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long i; u64 control; /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; - iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; + iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; + iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; + iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH; + iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC; /* Sabre's IOMMU lacks ctx flushing. */ iommu->iommu_ctxflush = 0; /* Invalidate TLB Entries. */ - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); + control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); control |= SABRE_IOMMUCTRL_DENAB; - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); for(i = 0; i < 16; i++) { - sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); } /* Leave diag mode enabled for full-flushing done @@ -698,10 +974,10 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm, */ pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask); - sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(iommu->page_table)); - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); + control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); control |= SABRE_IOMMUCTRL_ENAB; switch(tsbsize) { @@ -716,24 +992,22 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm, prom_halt(); break; } - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); } -static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp) { + struct pci_pbm_info *pbm; + + pbm = &p->pbm_A; pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); - pbm->scan_bus = sabre_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; pbm->prom_node = dp; - pci_get_pbm_props(pbm); + pbm->pci_first_busno = p->pci_first_busno; + pbm->pci_last_busno = p->pci_last_busno; pci_determine_mem_io_space(pbm); } @@ -742,9 +1016,9 @@ void sabre_init(struct device_node *dp, char *model_name) { const struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; - struct pci_pbm_info *pbm; struct iommu *iommu; int tsbsize; + const u32 *busrange; const u32 *vdma; u32 upa_portid, dma_mask; u64 clear_irq; @@ -779,15 +1053,17 @@ void sabre_init(struct device_node *dp, char *model_name) prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_halt(); } - pbm = &p->pbm_A; - pbm->iommu = iommu; + p->pbm_A.iommu = iommu; upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; + p->next = pci_controller_root; + pci_controller_root = p; - pbm->portid = upa_portid; + p->pbm_A.portid = upa_portid; + p->index = pci_num_controllers++; + p->scan_bus = sabre_scan_bus; + p->pci_ops = &sabre_ops; /* * Map in SABRE register set and report the presence of this SABRE. @@ -798,26 +1074,26 @@ void sabre_init(struct device_node *dp, char *model_name) /* * First REG in property is base of entire SABRE register space. */ - pbm->controller_regs = pr_regs[0].phys_addr; + p->pbm_A.controller_regs = pr_regs[0].phys_addr; /* Clear interrupts */ /* PCI first */ for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); /* Then OBIO */ for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); /* Error interrupts are enabled later after the bus scan. */ - sabre_write(pbm->controller_regs + SABRE_PCICTRL, + sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL, (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - pbm->config_space = - (pbm->controller_regs + SABRE_CONFIGSPACE); + p->pbm_A.config_space = + (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); vdma = of_get_property(dp, "virtual-dma", NULL); @@ -841,10 +1117,14 @@ void sabre_init(struct device_node *dp, char *model_name) prom_halt(); } - sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); + sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); + + busrange = of_get_property(dp, "bus-range", NULL); + p->pci_first_busno = busrange[0]; + p->pci_last_busno = busrange[1]; /* * Look for APB underneath. */ - sabre_pbm_init(p, pbm, dp); + sabre_pbm_init(p, dp); } diff --git a/trunk/arch/sparc64/kernel/pci_schizo.c b/trunk/arch/sparc64/kernel/pci_schizo.c index ae76898bbe2b..91a7385e5d32 100644 --- a/trunk/arch/sparc64/kernel/pci_schizo.c +++ b/trunk/arch/sparc64/kernel/pci_schizo.c @@ -10,13 +10,12 @@ #include #include +#include #include #include #include #include #include -#include -#include #include "pci_impl.h" #include "iommu_common.h" @@ -104,6 +103,125 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm, SCHIZO_CONFIG_ENCODE(bus, devfn, where)); } +/* Just make sure the bus number is in range. */ +static int schizo_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + if (bus < pbm->pci_first_busno || + bus > pbm->pci_last_busno) + return 1; + return 0; +} + +/* SCHIZO PCI configuration space accessors. */ + +static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (schizo_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (schizo_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops schizo_ops = { + .read = schizo_read_pci_cfg, + .write = schizo_write_pci_cfg, +}; + /* SCHIZO error handling support. */ enum schizo_error_type { UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR @@ -120,6 +238,25 @@ static unsigned long stc_line_buf[16]; #define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */ #define SCHIZO_SERR_INO 0x34 /* Safari interface error */ +struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) +{ + ino &= IMAP_INO; + if (p->pbm_A.ino_bitmap & (1UL << ino)) + return &p->pbm_A; + if (p->pbm_B.ino_bitmap & (1UL << ino)) + return &p->pbm_B; + + printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps " + "PBM_A[%016lx] PBM_B[%016lx]", + p->index, ino, + p->pbm_A.ino_bitmap, + p->pbm_B.ino_bitmap); + printk("PCI%d: Using PBM_A, report this problem immediately.\n", + p->index); + + return &p->pbm_A; +} + #define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */ #define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */ #define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */ @@ -385,10 +522,9 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, static irqreturn_t schizo_ue_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; - unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; - unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR; + unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR; unsigned long afsr, afar, error_bits; int reported, limit; @@ -413,28 +549,28 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) schizo_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Uncorrectable Error, primary error type[%s]\n", - pbm->name, + printk("PCI%d: Uncorrectable Error, primary error type[%s]\n", + p->index, (((error_bits & SCHIZO_UEAFSR_PPIO) ? "PIO" : ((error_bits & SCHIZO_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & SCHIZO_UEAFSR_PDWR) ? "DMA Write" : "???"))))); - printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - pbm->name, + printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", + p->index, (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - pbm->name, + printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", + p->index, (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: UE Secondary errors [", pbm->name); + printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar); + printk("PCI%d: UE Secondary errors [", p->index); reported = 0; if (afsr & SCHIZO_UEAFSR_SPIO) { reported++; @@ -474,9 +610,9 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) static irqreturn_t schizo_ce_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg = pbm->controller_regs + SCHIZO_CE_AFSR; - unsigned long afar_reg = pbm->controller_regs + SCHIZO_CE_AFAR; + struct pci_controller_info *p = dev_id; + unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR; + unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR; unsigned long afsr, afar, error_bits; int reported, limit; @@ -501,8 +637,8 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) schizo_write(afsr_reg, error_bits); /* Log the error. */ - printk("%s: Correctable Error, primary error type[%s]\n", - pbm->name, + printk("PCI%d: Correctable Error, primary error type[%s]\n", + p->index, (((error_bits & SCHIZO_CEAFSR_PPIO) ? "PIO" : ((error_bits & SCHIZO_CEAFSR_PDRD) ? @@ -513,20 +649,20 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - pbm->name, + printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", + p->index, (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - pbm->name, + printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", + p->index, (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); - printk("%s: CE Secondary errors [", pbm->name); + printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar); + printk("PCI%d: CE Secondary errors [", p->index); reported = 0; if (afsr & SCHIZO_CEAFSR_SPIO) { reported++; @@ -745,10 +881,10 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { schizo_check_iommu_error(p, PCI_ERR); - pci_scan_for_target_abort(pbm, pbm->pci_bus); + pci_scan_for_target_abort(p, pbm, pbm->pci_bus); } if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); + pci_scan_for_master_abort(p, pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive @@ -758,7 +894,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); + pci_scan_for_parity_error(p, pbm, pbm->pci_bus); return IRQ_HANDLED; } @@ -804,23 +940,22 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) { - struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; + struct pci_controller_info *p = dev_id; u64 errlog; - errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, + errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG); + schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG, errlog & ~(SAFARI_ERRLOG_ERROUT)); if (!(errlog & BUS_ERROR_UNMAP)) { - printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", - pbm->name, errlog); + printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", + p->index, errlog); return IRQ_HANDLED; } - printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", - pbm->name); + printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", + p->index); schizo_check_iommu_error(p, SAFARI_ERR); return IRQ_HANDLED; @@ -837,16 +972,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) #define SCHIZO_SAFARI_IRQCTRL 0x10010UL #define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL -static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) -{ - ino &= IMAP_INO; - - if (pbm->ino_bitmap & (1UL << ino)) - return 1; - - return 0; -} - /* How the Tomatillo IRQs are routed around is pure guesswork here. * * All the Tomatillo devices I see in prtconf dumps seem to have only @@ -861,11 +986,11 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) * PCI bus units of the same Tomatillo. I still have not really * figured this out... */ -static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) +static void tomatillo_register_error_handlers(struct pci_controller_info *p) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct pci_pbm_info *pbm; + struct of_device *op; u64 tmp, err_mask, err_no_mask; - int err; /* Tomatillo IRQ property layout is: * 0: PCIERR @@ -875,42 +1000,44 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) * 4: POWER FAIL? */ - if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) { - err = request_irq(op->irqs[1], schizo_ue_intr, 0, - "TOMATILLO_UE", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register UE, " - "err=%d\n", pbm->name, err); - } - if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { - err = request_irq(op->irqs[2], schizo_ce_intr, 0, - "TOMATILLO_CE", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register CE, " - "err=%d\n", pbm->name, err); - } - err = 0; - if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, - "TOMATILLO_PCIERR", pbm); - } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, - "TOMATILLO_PCIERR", pbm); - } - if (err) - printk(KERN_WARNING "%s: Could not register PCIERR, " - "err=%d\n", pbm->name, err); - - if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { - err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, - "TOMATILLO_SERR", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register SERR, " - "err=%d\n", pbm->name, err); - } + pbm = pbm_for_ino(p, SCHIZO_UE_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, + "TOMATILLO_UE", p); + + pbm = pbm_for_ino(p, SCHIZO_CE_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, + "TOMATILLO CE", p); + + pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, + "TOMATILLO PCIERR-A", pbm); + + + pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, + "TOMATILLO PCIERR-B", pbm); + + pbm = pbm_for_ino(p, SCHIZO_SERR_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, + "TOMATILLO SERR", p); /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, + schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, + (SCHIZO_ECCCTRL_EE | + SCHIZO_ECCCTRL_UE | + SCHIZO_ECCCTRL_CE)); + + schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL, (SCHIZO_ECCCTRL_EE | SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_CE)); @@ -926,10 +1053,15 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) err_no_mask = SCHIZO_PCICTRL_DTO_ERR; - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); + + tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); + tmp |= err_mask; + tmp &= ~err_no_mask; + schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | @@ -938,7 +1070,8 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_STTO); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); + schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask); + schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask); err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | @@ -950,18 +1083,22 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_APERR | BUS_ERROR_UNMAP | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, + schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, + (SCHIZO_SAFERRCTRL_EN | err_mask)); + schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL, (SCHIZO_SAFERRCTRL_EN | err_mask)); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, + schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, + (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); + schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL, (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); } -static void schizo_register_error_handlers(struct pci_pbm_info *pbm) +static void schizo_register_error_handlers(struct pci_controller_info *p) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct pci_pbm_info *pbm; + struct of_device *op; u64 tmp, err_mask, err_no_mask; - int err; /* Schizo IRQ property layout is: * 0: PCIERR @@ -971,42 +1108,39 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) * 4: POWER FAIL? */ - if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) { - err = request_irq(op->irqs[1], schizo_ue_intr, 0, - "SCHIZO_UE", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register UE, " - "err=%d\n", pbm->name, err); - } - if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { - err = request_irq(op->irqs[2], schizo_ce_intr, 0, - "SCHIZO_CE", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register CE, " - "err=%d\n", pbm->name, err); - } - err = 0; - if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, - "SCHIZO_PCIERR", pbm); - } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, - "SCHIZO_PCIERR", pbm); - } - if (err) - printk(KERN_WARNING "%s: Could not register PCIERR, " - "err=%d\n", pbm->name, err); - - if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { - err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, - "SCHIZO_SERR", pbm); - if (err) - printk(KERN_WARNING "%s: Could not register SERR, " - "err=%d\n", pbm->name, err); - } + pbm = pbm_for_ino(p, SCHIZO_UE_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, + "SCHIZO_UE", p); + + pbm = pbm_for_ino(p, SCHIZO_CE_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, + "SCHIZO CE", p); + + pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, + "SCHIZO PCIERR-A", pbm); + + + pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, + "SCHIZO PCIERR-B", pbm); + + pbm = pbm_for_ino(p, SCHIZO_SERR_INO); + op = of_find_device_by_node(pbm->prom_node); + if (op) + request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, + "SCHIZO SERR", p); /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, + schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, (SCHIZO_ECCCTRL_EE | SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_CE)); @@ -1025,12 +1159,25 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); + + schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, + (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | + SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | + SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | + SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | + SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | + SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, + tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); + tmp |= err_mask; + tmp &= ~err_no_mask; + schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); + + schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | @@ -1063,8 +1210,11 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); #endif - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, + schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, (SCHIZO_SAFERRCTRL_EN | err_mask)); + + schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, + (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); } static void pbm_config_busmastering(struct pci_pbm_info *pbm) @@ -1084,19 +1234,27 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void schizo_scan_bus(struct pci_pbm_info *pbm) +static void schizo_scan_bus(struct pci_controller_info *p) { - pbm_config_busmastering(pbm); - pbm->is_66mhz_capable = - (of_find_property(pbm->prom_node, "66mhz-capable", NULL) + pbm_config_busmastering(&p->pbm_B); + p->pbm_B.is_66mhz_capable = + (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) + != NULL); + pbm_config_busmastering(&p->pbm_A); + p->pbm_A.is_66mhz_capable = + (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + p->pbm_B.pci_bus = pci_scan_one_pbm(&p->pbm_B); + p->pbm_A.pci_bus = pci_scan_one_pbm(&p->pbm_A); - if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) - tomatillo_register_error_handlers(pbm); + /* After the PCI bus scan is complete, we can register + * the error interrupt handlers. + */ + if (p->pbm_B.chip_type == PBM_CHIP_TYPE_TOMATILLO) + tomatillo_register_error_handlers(p); else - schizo_register_error_handlers(pbm); + schizo_register_error_handlers(p); } #define SCHIZO_STRBUF_CONTROL (0x02800UL) @@ -1333,8 +1491,10 @@ static void schizo_pbm_init(struct pci_controller_info *p, int chip_type) { const struct linux_prom64_registers *regs; + const unsigned int *busrange; struct pci_pbm_info *pbm; const char *chipset_name; + const u32 *ino_bitmap; int is_pbm_a; switch (chip_type) { @@ -1371,15 +1531,6 @@ static void schizo_pbm_init(struct pci_controller_info *p, else pbm = &p->pbm_B; - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->scan_bus = schizo_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -1404,7 +1555,13 @@ static void schizo_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - pci_get_pbm_props(pbm); + ino_bitmap = of_get_property(dp, "ino-bitmap", NULL); + pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | + ((u64)ino_bitmap[0] << 0UL)); + + busrange = of_get_property(dp, "bus-range", NULL); + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; schizo_pbm_iommu_init(pbm); schizo_pbm_strbuf_init(pbm); @@ -1423,15 +1580,23 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) { struct pci_controller_info *p; - struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; portid = of_getintprop_default(dp, "portid", 0xff); - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + for (p = pci_controller_root; p; p = p->next) { + struct pci_pbm_info *pbm; + + if (p->pbm_A.prom_node && p->pbm_B.prom_node) + continue; + + pbm = (p->pbm_A.prom_node ? + &p->pbm_A : + &p->pbm_B); + if (portid_compare(pbm->portid, portid, chip_type)) { - schizo_pbm_init(pbm->parent, dp, portid, chip_type); + schizo_pbm_init(p, dp, portid, chip_type); return; } } @@ -1452,6 +1617,13 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->pbm_B.iommu = iommu; + p->next = pci_controller_root; + pci_controller_root = p; + + p->index = pci_num_controllers++; + p->scan_bus = schizo_scan_bus; + p->pci_ops = &schizo_ops; + /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index 34df4047587a..1ccf4c9a9a43 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -593,15 +594,112 @@ const struct pci_iommu_ops pci_sun4v_iommu_ops = { .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, }; -static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) +static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) +{ + if (bus < pbm->pci_first_busno || + bus > pbm->pci_last_busno) + return 1; + return 0; +} + +static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + u32 devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + if (pci_sun4v_out_of_range(pbm, bus, device, func)) { + ret = ~0UL; + } else { + ret = pci_sun4v_config_get(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size); +#if 0 + printk("rcfg: [%x:%x:%x:%d]=[%lx]\n", + devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, ret); +#endif + } + switch (size) { + case 1: + *value = ret & 0xff; + break; + case 2: + *value = ret & 0xffff; + break; + case 4: + *value = ret & 0xffffffff; + break; + }; + + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + u32 devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + if (pci_sun4v_out_of_range(pbm, bus, device, func)) { + /* Do nothing. */ + } else { + ret = pci_sun4v_config_put(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, value); +#if 0 + printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n", + devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, value, ret); +#endif + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_sun4v_ops = { + .read = pci_sun4v_read_pci_cfg, + .write = pci_sun4v_write_pci_cfg, +}; + + +static void pbm_scan_bus(struct pci_controller_info *p, + struct pci_pbm_info *pbm) +{ + pbm->pci_bus = pci_scan_one_pbm(pbm); +} + +static void pci_sun4v_scan_bus(struct pci_controller_info *p) { struct property *prop; struct device_node *dp; - dp = pbm->prom_node; - prop = of_find_property(dp, "66mhz-capable", NULL); - pbm->is_66mhz_capable = (prop != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + if ((dp = p->pbm_A.prom_node) != NULL) { + prop = of_find_property(dp, "66mhz-capable", NULL); + p->pbm_A.is_66mhz_capable = (prop != NULL); + + pbm_scan_bus(p, &p->pbm_A); + } + if ((dp = p->pbm_B.prom_node) != NULL) { + prop = of_find_property(dp, "66mhz-capable", NULL); + p->pbm_B.is_66mhz_capable = (prop != NULL); + + pbm_scan_bus(p, &p->pbm_B); + } /* XXX register error interrupt handlers XXX */ } @@ -704,6 +802,20 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) pbm->name, sz); } +static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) +{ + struct property *prop; + unsigned int *busrange; + + prop = of_find_property(pbm->prom_node, "bus-range", NULL); + + busrange = prop->value; + + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; + +} + #ifdef CONFIG_PCI_MSI struct pci_sun4v_msiq_entry { u64 version_type; @@ -907,6 +1019,114 @@ static int msi_queue_alloc(struct pci_pbm_info *pbm) return -EINVAL; } +static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) +{ + const u32 *val; + int len; + + val = of_get_property(pbm->prom_node, "#msi-eqs", &len); + if (!val || len != 4) + goto no_msi; + pbm->msiq_num = *val; + if (pbm->msiq_num) { + const struct msiq_prop { + u32 first_msiq; + u32 num_msiq; + u32 first_devino; + } *mqp; + const struct msi_range_prop { + u32 first_msi; + u32 num_msi; + } *mrng; + const struct addr_range_prop { + u32 msi32_high; + u32 msi32_low; + u32 msi32_len; + u32 msi64_high; + u32 msi64_low; + u32 msi64_len; + } *arng; + + val = of_get_property(pbm->prom_node, "msi-eq-size", &len); + if (!val || len != 4) + goto no_msi; + + pbm->msiq_ent_count = *val; + + mqp = of_get_property(pbm->prom_node, + "msi-eq-to-devino", &len); + if (!mqp || len != sizeof(struct msiq_prop)) + goto no_msi; + + pbm->msiq_first = mqp->first_msiq; + pbm->msiq_first_devino = mqp->first_devino; + + val = of_get_property(pbm->prom_node, "#msi", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_num = *val; + + mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); + if (!mrng || len != sizeof(struct msi_range_prop)) + goto no_msi; + pbm->msi_first = mrng->first_msi; + + val = of_get_property(pbm->prom_node, "msi-data-mask", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_data_mask = *val; + + val = of_get_property(pbm->prom_node, "msix-data-width", &len); + if (!val || len != 4) + goto no_msi; + pbm->msix_data_width = *val; + + arng = of_get_property(pbm->prom_node, "msi-address-ranges", + &len); + if (!arng || len != sizeof(struct addr_range_prop)) + goto no_msi; + pbm->msi32_start = ((u64)arng->msi32_high << 32) | + (u64) arng->msi32_low; + pbm->msi64_start = ((u64)arng->msi64_high << 32) | + (u64) arng->msi64_low; + pbm->msi32_len = arng->msi32_len; + pbm->msi64_len = arng->msi64_len; + + if (msi_bitmap_alloc(pbm)) + goto no_msi; + + if (msi_queue_alloc(pbm)) { + msi_bitmap_free(pbm); + goto no_msi; + } + + printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " + "devino[0x%x]\n", + pbm->name, + pbm->msiq_first, pbm->msiq_num, + pbm->msiq_ent_count, + pbm->msiq_first_devino); + printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " + "width[%u]\n", + pbm->name, + pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, + pbm->msix_data_width); + printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " + "addr64[0x%lx:0x%x]\n", + pbm->name, + pbm->msi32_start, pbm->msi32_len, + pbm->msi64_start, pbm->msi64_len); + printk(KERN_INFO "%s: MSI queues at RA [%p]\n", + pbm->name, + pbm->msi_queues); + } + + return; + +no_msi: + pbm->msiq_num = 0; + printk(KERN_INFO "%s: No MSI support.\n", pbm->name); +} static int alloc_msi(struct pci_pbm_info *pbm) { @@ -1025,117 +1245,6 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, */ sun4v_destroy_msi(virt_irq); } - -static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) -{ - const u32 *val; - int len; - - val = of_get_property(pbm->prom_node, "#msi-eqs", &len); - if (!val || len != 4) - goto no_msi; - pbm->msiq_num = *val; - if (pbm->msiq_num) { - const struct msiq_prop { - u32 first_msiq; - u32 num_msiq; - u32 first_devino; - } *mqp; - const struct msi_range_prop { - u32 first_msi; - u32 num_msi; - } *mrng; - const struct addr_range_prop { - u32 msi32_high; - u32 msi32_low; - u32 msi32_len; - u32 msi64_high; - u32 msi64_low; - u32 msi64_len; - } *arng; - - val = of_get_property(pbm->prom_node, "msi-eq-size", &len); - if (!val || len != 4) - goto no_msi; - - pbm->msiq_ent_count = *val; - - mqp = of_get_property(pbm->prom_node, - "msi-eq-to-devino", &len); - if (!mqp || len != sizeof(struct msiq_prop)) - goto no_msi; - - pbm->msiq_first = mqp->first_msiq; - pbm->msiq_first_devino = mqp->first_devino; - - val = of_get_property(pbm->prom_node, "#msi", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_num = *val; - - mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); - if (!mrng || len != sizeof(struct msi_range_prop)) - goto no_msi; - pbm->msi_first = mrng->first_msi; - - val = of_get_property(pbm->prom_node, "msi-data-mask", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_data_mask = *val; - - val = of_get_property(pbm->prom_node, "msix-data-width", &len); - if (!val || len != 4) - goto no_msi; - pbm->msix_data_width = *val; - - arng = of_get_property(pbm->prom_node, "msi-address-ranges", - &len); - if (!arng || len != sizeof(struct addr_range_prop)) - goto no_msi; - pbm->msi32_start = ((u64)arng->msi32_high << 32) | - (u64) arng->msi32_low; - pbm->msi64_start = ((u64)arng->msi64_high << 32) | - (u64) arng->msi64_low; - pbm->msi32_len = arng->msi32_len; - pbm->msi64_len = arng->msi64_len; - - if (msi_bitmap_alloc(pbm)) - goto no_msi; - - if (msi_queue_alloc(pbm)) { - msi_bitmap_free(pbm); - goto no_msi; - } - - printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " - "devino[0x%x]\n", - pbm->name, - pbm->msiq_first, pbm->msiq_num, - pbm->msiq_ent_count, - pbm->msiq_first_devino); - printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " - "width[%u]\n", - pbm->name, - pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, - pbm->msix_data_width); - printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " - "addr64[0x%lx:0x%x]\n", - pbm->name, - pbm->msi32_start, pbm->msi32_len, - pbm->msi64_start, pbm->msi64_len); - printk(KERN_INFO "%s: MSI queues at RA [%p]\n", - pbm->name, - pbm->msi_queues); - } - pbm->setup_msi_irq = pci_sun4v_setup_msi_irq; - pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq; - - return; - -no_msi: - pbm->msiq_num = 0; - printk(KERN_INFO "%s: No MSI support.\n", pbm->name); -} #else /* CONFIG_PCI_MSI */ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) { @@ -1151,15 +1260,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node else pbm = &p->pbm_A; - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->scan_bus = pci_sun4v_scan_bus; - pbm->pci_ops = &sun4v_pci_ops; - pbm->config_space_reg_bits = 12; - - pbm->index = pci_num_pbms++; - pbm->parent = p; pbm->prom_node = dp; @@ -1171,7 +1271,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_determine_mem_io_space(pbm); - pci_get_pbm_props(pbm); + pci_sun4v_get_bus_range(pbm); pci_sun4v_iommu_init(pbm); pci_sun4v_msi_init(pbm); } @@ -1179,7 +1279,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node void sun4v_pci_init(struct device_node *dp, char *model_name) { struct pci_controller_info *p; - struct pci_pbm_info *pbm; struct iommu *iommu; struct property *prop; struct linux_prom64_registers *regs; @@ -1191,9 +1290,18 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + for (p = pci_controller_root; p; p = p->next) { + struct pci_pbm_info *pbm; + + if (p->pbm_A.prom_node && p->pbm_B.prom_node) + continue; + + pbm = (p->pbm_A.prom_node ? + &p->pbm_A : + &p->pbm_B); + if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(pbm->parent, dp, devhandle); + pci_sun4v_pbm_init(p, dp, devhandle); return; } } @@ -1223,6 +1331,18 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->pbm_B.iommu = iommu; + p->next = pci_controller_root; + pci_controller_root = p; + + p->index = pci_num_controllers++; + + p->scan_bus = pci_sun4v_scan_bus; +#ifdef CONFIG_PCI_MSI + p->setup_msi_irq = pci_sun4v_setup_msi_irq; + p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; +#endif + p->pci_ops = &pci_sun4v_ops; + /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. */ diff --git a/trunk/arch/sparc64/kernel/prom.c b/trunk/arch/sparc64/kernel/prom.c index b7976b14d0ba..c54d4d8af014 100644 --- a/trunk/arch/sparc64/kernel/prom.c +++ b/trunk/arch/sparc64/kernel/prom.c @@ -1636,21 +1636,10 @@ static struct device_node * __init create_node(phandle node, struct device_node static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) { - struct device_node *ret = NULL, *prev_sibling = NULL; struct device_node *dp; - while (1) { - dp = create_node(node, parent); - if (!dp) - break; - - if (prev_sibling) - prev_sibling->sibling = dp; - - if (!ret) - ret = dp; - prev_sibling = dp; - + dp = create_node(node, parent); + if (dp) { *(*nextp) = dp; *nextp = &dp->allnext; @@ -1659,10 +1648,10 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl dp->child = build_tree(dp, prom_getchild(node), nextp); - node = prom_getsibling(node); + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); } - return ret; + return dp; } void __init prom_build_devicetree(void) diff --git a/trunk/arch/sparc64/kernel/sbus.c b/trunk/arch/sparc64/kernel/sbus.c index 91f6e2a74ad5..3b05428cc909 100644 --- a/trunk/arch/sparc64/kernel/sbus.c +++ b/trunk/arch/sparc64/kernel/sbus.c @@ -1002,24 +1002,24 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) u64 control; irq = sbus_build_irq(sbus, SYSIO_UE_INO); - if (request_irq(irq, sysio_ue_handler, 0, - "SYSIO_UE", sbus) < 0) { + if (request_irq(irq, sysio_ue_handler, + IRQF_SHARED, "SYSIO UE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", sbus->portid); prom_halt(); } irq = sbus_build_irq(sbus, SYSIO_CE_INO); - if (request_irq(irq, sysio_ce_handler, 0, - "SYSIO_CE", sbus) < 0) { + if (request_irq(irq, sysio_ce_handler, + IRQF_SHARED, "SYSIO CE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", sbus->portid); prom_halt(); } irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); - if (request_irq(irq, sysio_sbus_error_handler, 0, - "SYSIO_SBERR", sbus) < 0) { + if (request_irq(irq, sysio_sbus_error_handler, + IRQF_SHARED, "SYSIO SBUS Error", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", sbus->portid); prom_halt(); diff --git a/trunk/arch/sparc64/kernel/sys_sparc32.c b/trunk/arch/sparc64/kernel/sys_sparc32.c index abd83129b2e7..692e46a6b8da 100644 --- a/trunk/arch/sparc64/kernel/sys_sparc32.c +++ b/trunk/arch/sparc64/kernel/sys_sparc32.c @@ -793,7 +793,7 @@ asmlinkage long sys32_utimes(char __user *filename, tv[1].tv_nsec = 1000 * ktvs[1].tv_usec; } - return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0); + return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL); } /* These are here just in case some old sparc32 binary calls it. */ diff --git a/trunk/arch/sparc64/kernel/systbls.S b/trunk/arch/sparc64/kernel/systbls.S index 5fe7f9ad4a92..48c36fe6dc62 100644 --- a/trunk/arch/sparc64/kernel/systbls.S +++ b/trunk/arch/sparc64/kernel/systbls.S @@ -81,7 +81,6 @@ sys_call_table32: .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare /*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait -/*310*/ .word compat_sys_utimensat #endif /* CONFIG_COMPAT */ @@ -153,7 +152,6 @@ sys_call_table: .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .word sys_utimensat #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -271,6 +269,5 @@ sunos_sys_table: .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys -/*310*/ .long sunos_nosys #endif diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index d0fde36395b4..dc652f210290 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/sparc64/mm/fault.c b/trunk/arch/sparc64/mm/fault.c index b582024d2199..c32e309f7788 100644 --- a/trunk/arch/sparc64/mm/fault.c +++ b/trunk/arch/sparc64/mm/fault.c @@ -32,23 +32,36 @@ #include #ifdef CONFIG_KPROBES -static inline int notify_page_fault(struct pt_regs *regs) +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) { - int ret = 0; - - /* kprobe_running() needs smp_processor_id() */ - if (!user_mode(regs)) { - preempt_disable(); - if (kprobe_running() && kprobe_fault_handler(regs, 0)) - ret = 1; - preempt_enable(); - } - return ret; + 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(struct pt_regs *regs) +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) { - return 0; + return NOTIFY_DONE; } #endif @@ -107,6 +120,9 @@ static void __kprobes unhandled_fault(unsigned long address, printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", (tsk->mm ? (unsigned long) tsk->mm->pgd : (unsigned long) tsk->active_mm->pgd)); + if (notify_die(DIE_GPF, "general protection fault", regs, + 0, 0, SIGSEGV) == NOTIFY_STOP) + return; die_if_kernel("Oops", regs); } @@ -283,7 +299,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) fault_code = get_thread_fault_code(); - if (notify_page_fault(regs)) + if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, + fault_code, 0, SIGSEGV) == NOTIFY_STOP) return; si_code = SEGV_MAPERR; diff --git a/trunk/arch/um/Kconfig b/trunk/arch/um/Kconfig index c504312219b4..354cc6b70530 100644 --- a/trunk/arch/um/Kconfig +++ b/trunk/arch/um/Kconfig @@ -277,8 +277,7 @@ config HIGHMEM config KERNEL_STACK_ORDER int "Kernel stack size order" - default 1 if 64BIT - default 0 if !64BIT + default 2 help This option determines the size of UML kernel stacks. They will be 1 << order pages. The default is OK unless you're running Valgrind @@ -321,7 +320,21 @@ source "crypto/Kconfig" source "lib/Kconfig" -source "drivers/scsi/Kconfig" +menu "SCSI support" +depends on BROKEN + +config SCSI + tristate "SCSI support" + +# This gives us free_dma, which scsi.c wants. +config GENERIC_ISA_DMA + bool + depends on SCSI + default y + +source "arch/um/Kconfig.scsi" + +endmenu source "drivers/md/Kconfig" diff --git a/trunk/arch/um/Kconfig.scsi b/trunk/arch/um/Kconfig.scsi new file mode 100644 index 000000000000..c291c942b1a8 --- /dev/null +++ b/trunk/arch/um/Kconfig.scsi @@ -0,0 +1,58 @@ +comment "SCSI support type (disk, tape, CD-ROM)" + depends on SCSI + +config BLK_DEV_SD + tristate "SCSI disk support" + depends on SCSI + +config SD_EXTRA_DEVS + int "Maximum number of SCSI disks that can be loaded as modules" + depends on BLK_DEV_SD + default "40" + +config CHR_DEV_ST + tristate "SCSI tape support" + depends on SCSI + +config BLK_DEV_SR + tristate "SCSI CD-ROM support" + depends on SCSI + +config BLK_DEV_SR_VENDOR + bool "Enable vendor-specific extensions (for SCSI CDROM)" + depends on BLK_DEV_SR + +config SR_EXTRA_DEVS + int "Maximum number of CDROM devices that can be loaded as modules" + depends on BLK_DEV_SR + default "2" + +config CHR_DEV_SG + tristate "SCSI generic support" + depends on SCSI + +comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" + depends on SCSI + +#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then +config SCSI_DEBUG_QUEUES + bool "Enable extra checks in new queueing code" + depends on SCSI + +#fi +config SCSI_MULTI_LUN + bool "Probe all LUNs on each SCSI device" + depends on SCSI + +config SCSI_CONSTANTS + bool "Verbose SCSI error reporting (kernel size +=12K)" + depends on SCSI + +config SCSI_LOGGING + bool "SCSI logging facility" + depends on SCSI + +config SCSI_DEBUG + tristate "SCSI debugging host simulator (EXPERIMENTAL)" + depends on SCSI + diff --git a/trunk/arch/um/defconfig b/trunk/arch/um/defconfig index a54d0efecae1..f938fa822146 100644 --- a/trunk/arch/um/defconfig +++ b/trunk/arch/um/defconfig @@ -86,7 +86,7 @@ CONFIG_MCONSOLE=y # CONFIG_MAGIC_SYSRQ is not set CONFIG_NEST_LEVEL=0 # CONFIG_HIGHMEM is not set -CONFIG_KERNEL_STACK_ORDER=0 +CONFIG_KERNEL_STACK_ORDER=2 CONFIG_UML_REAL_TIME_CLOCK=y # diff --git a/trunk/arch/um/include/common-offsets.h b/trunk/arch/um/include/common-offsets.h index 541f4a8ca512..5593a8027083 100644 --- a/trunk/arch/um/include/common-offsets.h +++ b/trunk/arch/um/include/common-offsets.h @@ -28,5 +28,3 @@ DEFINE(UM_NR_CPUS, NR_CPUS); /* For crypto assembler code. */ DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); - -DEFINE(UM_THREAD_SIZE, THREAD_SIZE); diff --git a/trunk/arch/um/include/kern_util.h b/trunk/arch/um/include/kern_util.h index 8d7f7c1cb9c6..50a49691e0e6 100644 --- a/trunk/arch/um/include/kern_util.h +++ b/trunk/arch/um/include/kern_util.h @@ -117,7 +117,4 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs); extern void copy_sc(union uml_pt_regs *regs, void *from); -unsigned long to_irq_stack(int sig, unsigned long *mask_out); -unsigned long from_irq_stack(int nested); - #endif diff --git a/trunk/arch/um/include/os.h b/trunk/arch/um/include/os.h index 4d9fb26387d5..688d181b5f8a 100644 --- a/trunk/arch/um/include/os.h +++ b/trunk/arch/um/include/os.h @@ -272,6 +272,7 @@ extern void do_longjmp(void *p, int val); /* util.c */ extern void stack_protections(unsigned long address); +extern void task_protections(unsigned long address); extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); diff --git a/trunk/arch/um/include/sysdep-i386/archsetjmp.h b/trunk/arch/um/include/sysdep-i386/archsetjmp.h index 0f312085ce1d..11bafab669e9 100644 --- a/trunk/arch/um/include/sysdep-i386/archsetjmp.h +++ b/trunk/arch/um/include/sysdep-i386/archsetjmp.h @@ -1,5 +1,5 @@ /* - * arch/um/include/sysdep-i386/archsetjmp.h + * arch/i386/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H diff --git a/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h b/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h index 2af8f12ca161..9a5e1a6ec800 100644 --- a/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h +++ b/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h @@ -1,5 +1,5 @@ /* - * arch/um/include/sysdep-x86_64/archsetjmp.h + * arch/x86_64/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H diff --git a/trunk/arch/um/kernel/dyn.lds.S b/trunk/arch/um/kernel/dyn.lds.S index 87a4e4427d8d..e36f92b463ce 100644 --- a/trunk/arch/um/kernel/dyn.lds.S +++ b/trunk/arch/um/kernel/dyn.lds.S @@ -97,8 +97,6 @@ SECTIONS .data : { . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ *(.data.init_task) - . = ALIGN(KERNEL_STACK_SIZE); - *(.data.init_irqstack) *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } diff --git a/trunk/arch/um/kernel/init_task.c b/trunk/arch/um/kernel/init_task.c index d4f1d1ab252b..cda91aa8e703 100644 --- a/trunk/arch/um/kernel/init_task.c +++ b/trunk/arch/um/kernel/init_task.c @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com) +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -33,20 +33,28 @@ EXPORT_SYMBOL(init_task); /* * Initial thread structure. * - * We need to make sure that this is aligned due to the + * We need to make sure that this is 16384-byte aligned due to the * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; - -union thread_union cpu0_irqstack - __attribute__((__section__(".data.init_irqstack"))) = - { INIT_THREAD_INFO(init_task) }; +union thread_union init_thread_union +__attribute__((__section__(".data.init_task"))) = +{ INIT_THREAD_INFO(init_task) }; void unprotect_stack(unsigned long stack) { - os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0); + os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, + 1, 1, 0); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/irq.c b/trunk/arch/um/kernel/irq.c index dba04d88b432..8f2ed3690315 100644 --- a/trunk/arch/um/kernel/irq.c +++ b/trunk/arch/um/kernel/irq.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: @@ -32,7 +32,6 @@ #include "sigio.h" #include "um_malloc.h" #include "misc_constants.h" -#include "as-layout.h" /* * Generic, controller-independent functions: @@ -54,7 +53,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; - if (!action) + if (!action) goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP @@ -469,113 +468,3 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) out: return err; } - -/* - * IRQ stack entry and exit: - * - * Unlike i386, UML doesn't receive IRQs on the normal kernel stack - * and switch over to the IRQ stack after some preparation. We use - * sigaltstack to receive signals on a separate stack from the start. - * These two functions make sure the rest of the kernel won't be too - * upset by being on a different stack. The IRQ stack has a - * thread_info structure at the bottom so that current et al continue - * to work. - * - * to_irq_stack copies the current task's thread_info to the IRQ stack - * thread_info and sets the tasks's stack to point to the IRQ stack. - * - * from_irq_stack copies the thread_info struct back (flags may have - * been modified) and resets the task's stack pointer. - * - * Tricky bits - - * - * What happens when two signals race each other? UML doesn't block - * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal - * could arrive while a previous one is still setting up the - * thread_info. - * - * There are three cases - - * The first interrupt on the stack - sets up the thread_info and - * handles the interrupt - * A nested interrupt interrupting the copying of the thread_info - - * can't handle the interrupt, as the stack is in an unknown state - * A nested interrupt not interrupting the copying of the - * thread_info - doesn't do any setup, just handles the interrupt - * - * The first job is to figure out whether we interrupted stack setup. - * This is done by xchging the signal mask with thread_info->pending. - * If the value that comes back is zero, then there is no setup in - * progress, and the interrupt can be handled. If the value is - * non-zero, then there is stack setup in progress. In order to have - * the interrupt handled, we leave our signal in the mask, and it will - * be handled by the upper handler after it has set up the stack. - * - * Next is to figure out whether we are the outer handler or a nested - * one. As part of setting up the stack, thread_info->real_thread is - * set to non-NULL (and is reset to NULL on exit). This is the - * nesting indicator. If it is non-NULL, then the stack is already - * set up and the handler can run. - */ - -static unsigned long pending_mask; - -unsigned long to_irq_stack(int sig, unsigned long *mask_out) -{ - struct thread_info *ti; - unsigned long mask, old; - int nested; - - mask = xchg(&pending_mask, 1 << sig); - if(mask != 0){ - /* If any interrupts come in at this point, we want to - * make sure that their bits aren't lost by our - * putting our bit in. So, this loop accumulates bits - * until xchg returns the same value that we put in. - * When that happens, there were no new interrupts, - * and pending_mask contains a bit for each interrupt - * that came in. - */ - old = 1 << sig; - do { - old |= mask; - mask = xchg(&pending_mask, old); - } while(mask != old); - return 1; - } - - ti = current_thread_info(); - nested = (ti->real_thread != NULL); - if(!nested){ - struct task_struct *task; - struct thread_info *tti; - - task = cpu_tasks[ti->cpu].task; - tti = task_thread_info(task); - *ti = *tti; - ti->real_thread = tti; - task->stack = ti; - } - - mask = xchg(&pending_mask, 0); - *mask_out |= mask | nested; - return 0; -} - -unsigned long from_irq_stack(int nested) -{ - struct thread_info *ti, *to; - unsigned long mask; - - ti = current_thread_info(); - - pending_mask = 1; - - to = ti->real_thread; - current->stack = to; - ti->real_thread = NULL; - *to = *ti; - - mask = xchg(&pending_mask, 0); - return mask & ~1; -} - diff --git a/trunk/arch/um/kernel/skas/process.c b/trunk/arch/um/kernel/skas/process.c index 2a69a7ce5792..ef36facd8fe9 100644 --- a/trunk/arch/um/kernel/skas/process.c +++ b/trunk/arch/um/kernel/skas/process.c @@ -163,12 +163,8 @@ static int start_kernel_proc(void *unused) extern int userspace_pid[]; -extern char cpu0_irqstack[]; - int start_uml_skas(void) { - stack_protections((unsigned long) &cpu0_irqstack); - set_sigstack(cpu0_irqstack, THREAD_SIZE); if(proc_mm) userspace_pid[0] = start_userspace(0); @@ -182,23 +178,20 @@ int start_uml_skas(void) int external_pid_skas(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu return(userspace_pid[0]); } int thread_pid_skas(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu return(userspace_pid[0]); } void kill_off_processes_skas(void) { if(proc_mm) - /* - * FIXME: need to loop over userspace_pids in - * kill_off_processes_skas - */ +#warning need to loop over userspace_pids in kill_off_processes_skas os_kill_ptraced_process(userspace_pid[0], 1); else { struct task_struct *p; diff --git a/trunk/arch/um/kernel/tt/exec_kern.c b/trunk/arch/um/kernel/tt/exec_kern.c index 40126cb51801..98e21743e604 100644 --- a/trunk/arch/um/kernel/tt/exec_kern.c +++ b/trunk/arch/um/kernel/tt/exec_kern.c @@ -57,7 +57,7 @@ void flush_thread_tt(void) enable_timer(); free_page(stack); protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - stack_protections((unsigned long) current_thread); + task_protections((unsigned long) current_thread); force_flush_all(); unblock_signals(); } diff --git a/trunk/arch/um/kernel/tt/process_kern.c b/trunk/arch/um/kernel/tt/process_kern.c index 74347adf81bf..c631303cb800 100644 --- a/trunk/arch/um/kernel/tt/process_kern.c +++ b/trunk/arch/um/kernel/tt/process_kern.c @@ -209,7 +209,7 @@ void finish_fork_handler(int sig) if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - stack_protections((unsigned long) current_thread); + task_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); local_irq_disable(); diff --git a/trunk/arch/um/kernel/um_arch.c b/trunk/arch/um/kernel/um_arch.c index ecc458fe51b9..1cf954a47fd7 100644 --- a/trunk/arch/um/kernel/um_arch.c +++ b/trunk/arch/um/kernel/um_arch.c @@ -459,7 +459,7 @@ int __init linux_main(int argc, char **argv) uml_postsetup(); - stack_protections((unsigned long) &init_thread_info); + task_protections((unsigned long) &init_thread_info); os_flush_stdout(); return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); diff --git a/trunk/arch/um/kernel/uml.lds.S b/trunk/arch/um/kernel/uml.lds.S index bc59f97e34d0..f6301274cf3c 100644 --- a/trunk/arch/um/kernel/uml.lds.S +++ b/trunk/arch/um/kernel/uml.lds.S @@ -59,8 +59,6 @@ SECTIONS { . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ *(.data.init_task) - . = ALIGN(KERNEL_STACK_SIZE); - *(.data.init_irqstack) *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS diff --git a/trunk/arch/um/os-Linux/process.c b/trunk/arch/um/os-Linux/process.c index 2d9d2ca39299..92a7b59120d6 100644 --- a/trunk/arch/um/os-Linux/process.c +++ b/trunk/arch/um/os-Linux/process.c @@ -239,7 +239,6 @@ int __init can_drop_memory(void) return ok; } -#ifdef UML_CONFIG_MODE_TT void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) { int flags = 0, pages; @@ -261,7 +260,6 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) "errno = %d\n", errno); } } -#endif void init_new_thread_signals(void) { diff --git a/trunk/arch/um/os-Linux/signal.c b/trunk/arch/um/os-Linux/signal.c index 18e5c8b67eb8..48d493415301 100644 --- a/trunk/arch/um/os-Linux/signal.c +++ b/trunk/arch/um/os-Linux/signal.c @@ -61,19 +61,15 @@ void sig_handler(int sig, struct sigcontext *sc) static void real_alarm_handler(int sig, struct sigcontext *sc) { - union uml_pt_regs regs; - if(sig == SIGALRM) switch_timers(0); - if(sc != NULL) - copy_sc(®s, sc); - regs.skas.is_user = 0; - unblock_signals(); - timer_handler(sig, ®s); + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, + sig, sc); if(sig == SIGALRM) switch_timers(1); + } void alarm_handler(int sig, struct sigcontext *sc) @@ -117,46 +113,6 @@ void remove_sigstack(void) void (*handlers[_NSIG])(int sig, struct sigcontext *sc); -void handle_signal(int sig, struct sigcontext *sc) -{ - unsigned long pending = 0; - - do { - int nested, bail; - - /* - * pending comes back with one bit set for each - * interrupt that arrived while setting up the stack, - * plus a bit for this interrupt, plus the zero bit is - * set if this is a nested interrupt. - * If bail is true, then we interrupted another - * handler setting up the stack. In this case, we - * have to return, and the upper handler will deal - * with this interrupt. - */ - bail = to_irq_stack(sig, &pending); - if(bail) - return; - - nested = pending & 1; - pending &= ~1; - - while((sig = ffs(pending)) != 0){ - sig--; - pending &= ~(1 << sig); - (*handlers[sig])(sig, sc); - } - - /* Again, pending comes back with a mask of signals - * that arrived while tearing down the stack. If this - * is non-zero, we just go back, set up the stack - * again, and handle the new interrupts. - */ - if(!nested) - pending = from_irq_stack(nested); - } while(pending); -} - extern void hard_handler(int sig); void set_handler(int sig, void (*handler)(int), int flags, ...) diff --git a/trunk/arch/um/os-Linux/skas/mem.c b/trunk/arch/um/os-Linux/skas/mem.c index 5c8946320799..8e490fff3d47 100644 --- a/trunk/arch/um/os-Linux/skas/mem.c +++ b/trunk/arch/um/os-Linux/skas/mem.c @@ -68,7 +68,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) int err, pid = mm_idp->u.pid; if(proc_mm) - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu pid = userspace_pid[0]; multi_count++; diff --git a/trunk/arch/um/os-Linux/skas/process.c b/trunk/arch/um/os-Linux/skas/process.c index f9d2f8545afe..5c088a55396c 100644 --- a/trunk/arch/um/os-Linux/skas/process.c +++ b/trunk/arch/um/os-Linux/skas/process.c @@ -288,8 +288,7 @@ int start_userspace(unsigned long stub_stack) void userspace(union uml_pt_regs *regs) { int err, status, op, pid = userspace_pid[0]; - /* To prevent races if using_sysemu changes under us.*/ - int local_using_sysemu; + int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ while(1){ restore_registers(pid, regs); @@ -297,8 +296,7 @@ void userspace(union uml_pt_regs *regs) /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); - op = SELECT_PTRACE_OPERATION(local_using_sysemu, - singlestepping(NULL)); + op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); err = ptrace(op, pid, 0, 0); if(err) @@ -492,8 +490,8 @@ void map_stub_pages(int fd, unsigned long code, void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) { (*buf)[0].JB_IP = (unsigned long) handler; - (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE - - sizeof(void *); + (*buf)[0].JB_SP = (unsigned long) stack + + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); } #define INIT_JMP_NEW_THREAD 0 @@ -535,7 +533,8 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + - UM_THREAD_SIZE - sizeof(void *); + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - + sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); @@ -587,7 +586,7 @@ void switch_mm_skas(struct mm_id *mm_idp) { int err; - /* FIXME: need cpu pid in switch_mm_skas */ +#warning need cpu pid in switch_mm_skas if(proc_mm){ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); diff --git a/trunk/arch/um/os-Linux/sys-i386/signal.c b/trunk/arch/um/os-Linux/sys-i386/signal.c index f311609f93da..0d3eae518352 100644 --- a/trunk/arch/um/os-Linux/sys-i386/signal.c +++ b/trunk/arch/um/os-Linux/sys-i386/signal.c @@ -1,13 +1,15 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include -extern void handle_signal(int sig, struct sigcontext *sc); +extern void (*handlers[])(int sig, struct sigcontext *sc); void hard_handler(int sig) { - handle_signal(sig, (struct sigcontext *) (&sig + 1)); + struct sigcontext *sc = (struct sigcontext *) (&sig + 1); + + (*handlers[sig])(sig, sc); } diff --git a/trunk/arch/um/os-Linux/sys-x86_64/signal.c b/trunk/arch/um/os-Linux/sys-x86_64/signal.c index 82a388822cd3..3f369e5f976b 100644 --- a/trunk/arch/um/os-Linux/sys-x86_64/signal.c +++ b/trunk/arch/um/os-Linux/sys-x86_64/signal.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include -extern void handle_signal(int sig, struct sigcontext *sc); +extern void (*handlers[])(int sig, struct sigcontext *sc); void hard_handler(int sig) { struct ucontext *uc; asm("movq %%rdx, %0" : "=r" (uc)); - handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext); + (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); } diff --git a/trunk/arch/um/os-Linux/util.c b/trunk/arch/um/os-Linux/util.c index 7cbcf484e13d..c307a89ed259 100644 --- a/trunk/arch/um/os-Linux/util.c +++ b/trunk/arch/um/os-Linux/util.c @@ -33,8 +33,25 @@ void stack_protections(unsigned long address) { - if(mprotect((void *) address, UM_THREAD_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC) < 0) + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + + if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0) + panic("protecting stack failed, errno = %d", errno); +} + +void task_protections(unsigned long address) +{ + unsigned long guard = address + UM_KERN_PAGE_SIZE; + unsigned long stack = guard + UM_KERN_PAGE_SIZE; + int prot = 0, pages; + +#ifdef notdef + if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0) + panic("protecting guard page failed, errno = %d", errno); +#endif + pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; + prot = PROT_READ | PROT_WRITE | PROT_EXEC; + if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0) panic("protecting stack failed, errno = %d", errno); } @@ -55,7 +72,7 @@ int raw(int fd) /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ - return 0; + return(0); } void setup_machinename(char *machine_out) diff --git a/trunk/arch/v850/kernel/asm-offsets.c b/trunk/arch/v850/kernel/asm-offsets.c index cee5c3142d41..24f291369070 100644 --- a/trunk/arch/v850/kernel/asm-offsets.c +++ b/trunk/arch/v850/kernel/asm-offsets.c @@ -29,7 +29,7 @@ int main (void) DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace)); DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked)); DEFINE (TASK_THREAD, offsetof (struct task_struct, thread)); - DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack)); + DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info)); DEFINE (TASK_MM, offsetof (struct task_struct, mm)); DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm)); DEFINE (TASK_PID, offsetof (struct task_struct, pid)); diff --git a/trunk/arch/v850/kernel/entry.S b/trunk/arch/v850/kernel/entry.S index e4327a8d6bcd..8bc521ca081f 100644 --- a/trunk/arch/v850/kernel/entry.S +++ b/trunk/arch/v850/kernel/entry.S @@ -523,7 +523,7 @@ END(ret_from_trap) /* This the initial entry point for a new child thread, with an appropriate - stack in place that makes it look that the child is in the middle of an + stack in place that makes it look the the child is in the middle of an syscall. This function is actually `returned to' from switch_thread (copy_thread makes ret_from_fork the return address in each new thread's saved context). */ diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index 52be79beb306..f21068378272 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -716,7 +716,4 @@ ia32_sys_call_table: .quad sys_getcpu .quad sys_epoll_pwait .quad compat_sys_utimensat /* 320 */ - .quad sys_signalfd - .quad sys_timerfd - .quad sys_eventfd ia32_syscall_end: diff --git a/trunk/arch/x86_64/kernel/head64.c b/trunk/arch/x86_64/kernel/head64.c index 6c34bdd22e26..213d90e04755 100644 --- a/trunk/arch/x86_64/kernel/head64.c +++ b/trunk/arch/x86_64/kernel/head64.c @@ -62,6 +62,13 @@ void __init x86_64_start_kernel(char * real_mode_data) { int i; + /* + * Make sure kernel is aligned to 2MB address. Catching it at compile + * time is better. Change your config file and compile the kernel + * for a 2MB aligned address (CONFIG_PHYSICAL_START) + */ + BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1)); + /* clear bss before set_intr_gate with early_idt_handler */ clear_bss(); diff --git a/trunk/arch/x86_64/kernel/io_apic.c b/trunk/arch/x86_64/kernel/io_apic.c index d8bfe315471c..4d582589fa89 100644 --- a/trunk/arch/x86_64/kernel/io_apic.c +++ b/trunk/arch/x86_64/kernel/io_apic.c @@ -1413,7 +1413,7 @@ static void ack_apic_level(unsigned int irq) /* * We must acknowledge the irq before we move it or the acknowledge will - * not propagate properly. + * not propogate properly. */ ack_APIC_irq(); diff --git a/trunk/arch/x86_64/kernel/irq.c b/trunk/arch/x86_64/kernel/irq.c index 3eaceac32481..3bc30d2c13d3 100644 --- a/trunk/arch/x86_64/kernel/irq.c +++ b/trunk/arch/x86_64/kernel/irq.c @@ -32,7 +32,7 @@ atomic_t irq_err_count; */ static inline void stack_overflow_check(struct pt_regs *regs) { - u64 curbase = (u64)task_stack_page(current); + u64 curbase = (u64) current->thread_info; static unsigned long warned = -60*HZ; if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE && diff --git a/trunk/arch/x86_64/kernel/mce.c b/trunk/arch/x86_64/kernel/mce.c index a14375dd5425..442169640e45 100644 --- a/trunk/arch/x86_64/kernel/mce.c +++ b/trunk/arch/x86_64/kernel/mce.c @@ -720,11 +720,9 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: mce_create_device(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: mce_remove_device(cpu); break; } diff --git a/trunk/arch/x86_64/kernel/mce_amd.c b/trunk/arch/x86_64/kernel/mce_amd.c index 03356e64f9c8..d0bd5d66e103 100644 --- a/trunk/arch/x86_64/kernel/mce_amd.c +++ b/trunk/arch/x86_64/kernel/mce_amd.c @@ -654,11 +654,9 @@ static int threshold_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: threshold_create_device(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: threshold_remove_device(cpu); break; default: diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index d28f01379b9b..8c2ac41187c1 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -778,7 +778,6 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs) return; if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0) == NOTIFY_STOP) - return; if (!do_nmi_callback(regs,cpu)) unknown_nmi_error(reason, regs); diff --git a/trunk/arch/x86_64/kernel/vsyscall.c b/trunk/arch/x86_64/kernel/vsyscall.c index 51d4c6fa88c8..dc32cef96195 100644 --- a/trunk/arch/x86_64/kernel/vsyscall.c +++ b/trunk/arch/x86_64/kernel/vsyscall.c @@ -327,7 +327,7 @@ static int __cpuinit cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { long cpu = (long)arg; - if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) + if (action == CPU_ONLINE) smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); return NOTIFY_DONE; } diff --git a/trunk/arch/xtensa/kernel/asm-offsets.c b/trunk/arch/xtensa/kernel/asm-offsets.c index 698079b3a336..b256cfbef344 100644 --- a/trunk/arch/xtensa/kernel/asm-offsets.c +++ b/trunk/arch/xtensa/kernel/asm-offsets.c @@ -70,7 +70,7 @@ int main(void) DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm)); DEFINE(TASK_PID, offsetof (struct task_struct, pid)); DEFINE(TASK_THREAD, offsetof (struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info)); DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct)); BLANK(); diff --git a/trunk/arch/xtensa/kernel/pci-dma.c b/trunk/arch/xtensa/kernel/pci-dma.c index f5319d78c876..ca76f071666e 100644 --- a/trunk/arch/xtensa/kernel/pci-dma.c +++ b/trunk/arch/xtensa/kernel/pci-dma.c @@ -1,5 +1,5 @@ /* - * arch/xtensa/kernel/pci-dma.c + * arch/xtensa/pci-dma.c * * DMA coherent memory allocation. * diff --git a/trunk/block/as-iosched.c b/trunk/block/as-iosched.c index 109e91b91ffa..640aa839d63f 100644 --- a/trunk/block/as-iosched.c +++ b/trunk/block/as-iosched.c @@ -1306,7 +1306,7 @@ static void as_exit_queue(elevator_t *e) struct as_data *ad = e->elevator_data; del_timer_sync(&ad->antic_timer); - kblockd_flush_work(&ad->antic_work); + kblockd_flush(); BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index 93a2cf654597..b5664440896c 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -213,59 +213,6 @@ struct gendisk *get_gendisk(dev_t dev, int *part) return kobj ? to_disk(kobj) : NULL; } -/* - * print a full list of all partitions - intended for places where the root - * filesystem can't be mounted and thus to give the victim some idea of what - * went wrong - */ -void __init printk_all_partitions(void) -{ - int n; - struct gendisk *sgp; - - mutex_lock(&block_subsys_lock); - /* For each block device... */ - list_for_each_entry(sgp, &block_subsys.list, kobj.entry) { - char buf[BDEVNAME_SIZE]; - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - continue; - - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } /* partition subloop */ - } /* Block device loop */ - - mutex_unlock(&block_subsys_lock); - return; -} - #ifdef CONFIG_PROC_FS /* iterator */ static void *part_start(struct seq_file *part, loff_t *pos) diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 17e188973428..d99d402953a3 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -1704,7 +1704,7 @@ EXPORT_SYMBOL(blk_stop_queue); * on a queue, such as calling the unplug function after a timeout. * A block device may call blk_sync_queue to ensure that any * such activity is cancelled, thus allowing it to release resources - * that the callbacks might use. The caller must already have made sure + * the the callbacks might use. The caller must already have made sure * that its ->make_request_fn will not re-add plugging prior to calling * this function. * @@ -1712,6 +1712,7 @@ EXPORT_SYMBOL(blk_stop_queue); void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->unplug_timer); + kblockd_flush(); } EXPORT_SYMBOL(blk_sync_queue); @@ -3507,7 +3508,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action, * If a CPU goes away, splice its entries to the current CPU * and trigger a run of the softirq */ - if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { + if (action == CPU_DEAD) { int cpu = (unsigned long) hcpu; local_irq_disable(); @@ -3631,11 +3632,11 @@ int kblockd_schedule_work(struct work_struct *work) EXPORT_SYMBOL(kblockd_schedule_work); -void kblockd_flush_work(struct work_struct *work) +void kblockd_flush(void) { - cancel_work_sync(work); + flush_workqueue(kblockd_workqueue); } -EXPORT_SYMBOL(kblockd_flush_work); +EXPORT_SYMBOL(kblockd_flush); int __init blk_dev_init(void) { diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index 4ca0ab3448d9..620e14cabdc6 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -271,7 +271,7 @@ config CRYPTO_SERPENT Keys are allowed to be from 0 to 256 bits in length, in steps of 8 bits. Also includes the 'Tnepres' algorithm, a reversed - variant of Serpent for compatibility with old kerneli.org code. + variant of Serpent for compatibility with old kerneli code. See also: diff --git a/trunk/crypto/cryptomgr.c b/trunk/crypto/cryptomgr.c index e5fb7cca5107..6958ea83ee44 100644 --- a/trunk/crypto/cryptomgr.c +++ b/trunk/crypto/cryptomgr.c @@ -24,6 +24,8 @@ #include "internal.h" struct cryptomgr_param { + struct task_struct *thread; + struct rtattr *tb[CRYPTOA_MAX]; struct { @@ -79,7 +81,6 @@ static int cryptomgr_probe(void *data) static int cryptomgr_schedule_probe(struct crypto_larval *larval) { - struct task_struct *thread; struct cryptomgr_param *param; const char *name = larval->alg.cra_name; const char *p; @@ -129,8 +130,8 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); - thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); - if (IS_ERR(thread)) + param->thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); + if (IS_ERR(param->thread)) goto err_free_param; return NOTIFY_STOP; diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index adad2f3d438a..26ca9031ea49 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_FUSION) += message/ -obj-$(CONFIG_FIREWIRE) += firewire/ obj-$(CONFIG_IEEE1394) += ieee1394/ obj-y += cdrom/ obj-y += auxdisplay/ diff --git a/trunk/drivers/acpi/dispatcher/dsmethod.c b/trunk/drivers/acpi/dispatcher/dsmethod.c index 1cbe61905824..1683e5c5b94c 100644 --- a/trunk/drivers/acpi/dispatcher/dsmethod.c +++ b/trunk/drivers/acpi/dispatcher/dsmethod.c @@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * Obtain the method mutex if necessary. Do not acquire mutex for a * recursive call. */ - if (!walk_state || - !obj_desc->method.mutex->mutex.owner_thread || - (walk_state->thread != - obj_desc->method.mutex->mutex.owner_thread)) { + if (acpi_os_get_thread_id() != + obj_desc->method.mutex->mutex.owner_thread_id) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) @@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, } /* Update the mutex and walk info and save the original sync_level */ + obj_desc->method.mutex->mutex.owner_thread_id = + acpi_os_get_thread_id(); if (walk_state) { obj_desc->method.mutex->mutex. original_sync_level = walk_state->thread->current_sync_level; - obj_desc->method.mutex->mutex.owner_thread = - walk_state->thread; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { @@ -569,7 +567,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, acpi_os_release_mutex(method_desc->method.mutex->mutex. os_mutex); - method_desc->method.mutex->mutex.owner_thread = NULL; + method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; } } diff --git a/trunk/drivers/acpi/dispatcher/dsopcode.c b/trunk/drivers/acpi/dispatcher/dsopcode.c index fc9da4879cbf..6c6104a7a247 100644 --- a/trunk/drivers/acpi/dispatcher/dsopcode.c +++ b/trunk/drivers/acpi/dispatcher/dsopcode.c @@ -866,7 +866,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) - && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + && (op->common.parent->common.aml_opcode != + AML_NAME_OP))) { walk_state->result_obj = obj_desc; } } diff --git a/trunk/drivers/acpi/dispatcher/dsutils.c b/trunk/drivers/acpi/dispatcher/dsutils.c index 71503c036f7c..e4073e05a75c 100644 --- a/trunk/drivers/acpi/dispatcher/dsutils.c +++ b/trunk/drivers/acpi/dispatcher/dsutils.c @@ -556,9 +556,10 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * indicate this to the interpreter, set the * object to the root */ - obj_desc = ACPI_CAST_PTR(union - acpi_operand_object, - acpi_gbl_root_node); + obj_desc = + ACPI_CAST_PTR(union + acpi_operand_object, + acpi_gbl_root_node); status = AE_OK; } else { /* diff --git a/trunk/drivers/acpi/dispatcher/dswstate.c b/trunk/drivers/acpi/dispatcher/dswstate.c index 5afcdd9c7449..16c8e38b51ef 100644 --- a/trunk/drivers/acpi/dispatcher/dswstate.c +++ b/trunk/drivers/acpi/dispatcher/dswstate.c @@ -630,9 +630,12 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) * ******************************************************************************/ -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *method_desc, struct acpi_thread_state +struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *method_desc, + struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 82f496c07675..e08cf98f504f 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -147,10 +147,9 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, - unsigned count, int force_poll) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) { - if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) { + if (acpi_ec_mode == EC_POLL) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event, 0)) @@ -174,15 +173,14 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { int result = 0; unsigned count = atomic_read(&ec->event_count); acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", command); @@ -193,7 +191,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", command); @@ -204,7 +202,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); @@ -219,8 +217,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { int status; u32 glk; @@ -243,7 +240,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, /* Make sure GPE is enabled before doing transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_DEBUG PREFIX "input buffer is not empty, aborting transaction\n"); @@ -252,8 +249,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, status = acpi_ec_transaction_unlocked(ec, command, wdata, wdata_len, - rdata, rdata_len, - force_poll); + rdata, rdata_len); end: @@ -271,12 +267,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; - return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); + return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1); } int acpi_ec_burst_disable(struct acpi_ec *ec) { - return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); + return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0); } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) @@ -285,7 +281,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) u8 d; result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1, 0); + &address, 1, &d, 1); *data = d; return result; } @@ -294,7 +290,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0, 0); + wdata, 2, NULL, 0); } /* @@ -353,15 +349,13 @@ EXPORT_SYMBOL(ec_write); int ec_transaction(u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { if (!first_ec) return -ENODEV; return acpi_ec_transaction(first_ec, command, wdata, - wdata_len, rdata, rdata_len, - force_poll); + wdata_len, rdata, rdata_len); } EXPORT_SYMBOL(ec_transaction); @@ -380,7 +374,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); if (result) return result; @@ -416,7 +410,6 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; u8 value; struct acpi_ec *ec = data; - atomic_inc(&ec->event_count); if (acpi_ec_mode == EC_INTR) { diff --git a/trunk/drivers/acpi/events/evgpe.c b/trunk/drivers/acpi/events/evgpe.c index e22f4a973c0f..635ba449ebc2 100644 --- a/trunk/drivers/acpi/events/evgpe.c +++ b/trunk/drivers/acpi/events/evgpe.c @@ -341,8 +341,9 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, /* A Non-NULL gpe_device means this is a GPE Block Device */ - obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) - gpe_device); + obj_desc = + acpi_ns_get_attached_object((struct acpi_namespace_node *) + gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); } diff --git a/trunk/drivers/acpi/events/evgpeblk.c b/trunk/drivers/acpi/events/evgpeblk.c index 902c287b3a4f..ad5bc76edf46 100644 --- a/trunk/drivers/acpi/events/evgpeblk.c +++ b/trunk/drivers/acpi/events/evgpeblk.c @@ -1033,7 +1033,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) - && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { + && (gpe_event_info-> + flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } diff --git a/trunk/drivers/acpi/events/evmisc.c b/trunk/drivers/acpi/events/evmisc.c index 21cb749d0c75..cae786ca8600 100644 --- a/trunk/drivers/acpi/events/evmisc.c +++ b/trunk/drivers/acpi/events/evmisc.c @@ -196,12 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); + acpi_ex_exit_interpreter(); + + acpi_ev_notify_dispatch(notify_info); + + status = acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); + return_ACPI_STATUS(status); } + } if (!handler_obj) { @@ -320,9 +323,8 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_gbl_global_lock_acquired = TRUE; /* Send a unit to the semaphore */ - if (ACPI_FAILURE - (acpi_os_signal_semaphore - (acpi_gbl_global_lock_semaphore, 1))) { + if (ACPI_FAILURE(acpi_os_signal_semaphore( + acpi_gbl_global_lock_semaphore, 1))) { ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); } @@ -448,9 +450,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) } if (ACPI_FAILURE(status)) { - status = - acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, - timeout); + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/events/evregion.c b/trunk/drivers/acpi/events/evregion.c index e99f0c435a47..96b0e8431748 100644 --- a/trunk/drivers/acpi/events/evregion.c +++ b/trunk/drivers/acpi/events/evregion.c @@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 bit_width, acpi_integer * value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; @@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } /* Check for failure of the Region Setup */ @@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/events/evrgnini.c b/trunk/drivers/acpi/events/evrgnini.c index 400d90fca966..a4fa7e6822a3 100644 --- a/trunk/drivers/acpi/events/evrgnini.c +++ b/trunk/drivers/acpi/events/evrgnini.c @@ -228,8 +228,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* Install a handler for this PCI root bridge */ - status = - acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* diff --git a/trunk/drivers/acpi/events/evxface.c b/trunk/drivers/acpi/events/evxface.c index 6d866a01f5f4..a3379bafa676 100644 --- a/trunk/drivers/acpi/events/evxface.c +++ b/trunk/drivers/acpi/events/evxface.c @@ -91,6 +91,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_install_fixed_event_handler @@ -767,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_ex_enter_interpreter(); status = acpi_ev_acquire_global_lock(timeout); acpi_ex_exit_interpreter(); diff --git a/trunk/drivers/acpi/events/evxfevnt.c b/trunk/drivers/acpi/events/evxfevnt.c index 9cbd3414a574..17065e98807c 100644 --- a/trunk/drivers/acpi/events/evxfevnt.c +++ b/trunk/drivers/acpi/events/evxfevnt.c @@ -472,6 +472,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) } ACPI_EXPORT_SYMBOL(acpi_clear_gpe) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -567,6 +568,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_install_gpe_block diff --git a/trunk/drivers/acpi/executer/exconvrt.c b/trunk/drivers/acpi/executer/exconvrt.c index 79f2c0d42c06..d470e8b1f4ea 100644 --- a/trunk/drivers/acpi/executer/exconvrt.c +++ b/trunk/drivers/acpi/executer/exconvrt.c @@ -512,8 +512,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) */ - return_desc = acpi_ut_create_string_object((acpi_size) - (string_length - 1)); + return_desc = + acpi_ut_create_string_object((acpi_size) + (string_length - 1)); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/trunk/drivers/acpi/executer/excreate.c b/trunk/drivers/acpi/executer/excreate.c index 6e9a23e47fef..ae97812681a3 100644 --- a/trunk/drivers/acpi/executer/excreate.c +++ b/trunk/drivers/acpi/executer/excreate.c @@ -50,6 +50,7 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("excreate") + #ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * @@ -582,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start, * Get the sync_level. If method is serialized, a mutex will be * created for this method when it is parsed. */ - if (method_flags & AML_METHOD_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.sync_level = 0; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: sync_level = 0 * ACPI 2.0: sync_level = sync_level in method declaration diff --git a/trunk/drivers/acpi/executer/exdump.c b/trunk/drivers/acpi/executer/exdump.c index 51c9c29987c3..1a73c14df2c5 100644 --- a/trunk/drivers/acpi/executer/exdump.c +++ b/trunk/drivers/acpi/executer/exdump.c @@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = { static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), "Acquire Depth"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} @@ -451,8 +451,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) ACPI_FUNCTION_NAME(ex_dump_operand) - if (!((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_EXEC & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return; } @@ -843,8 +844,9 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) ACPI_FUNCTION_ENTRY(); if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return; } } @@ -1009,8 +1011,9 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return_VOID; } } diff --git a/trunk/drivers/acpi/executer/exmutex.c b/trunk/drivers/acpi/executer/exmutex.c index 6748e3ef0997..4eb883bda6ae 100644 --- a/trunk/drivers/acpi/executer/exmutex.c +++ b/trunk/drivers/acpi/executer/exmutex.c @@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * ******************************************************************************/ -void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) +void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc, + struct acpi_thread_state *thread) { - struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; - if (!thread) { return; } @@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); } /* Acquire the mutex, wait if necessary. Special case for Global Lock */ @@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Have the mutex: update mutex and walk info and save the sync_level */ - obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id(); obj_desc->mutex.acquisition_depth = 1; obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; @@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* The mutex must have been previously acquired in order to release it */ - if (!obj_desc->mutex.owner_thread) { + if (!obj_desc->mutex.owner_thread_id) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", acpi_ut_get_node_name(obj_desc->mutex.node))); @@ -266,15 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ - if ((obj_desc->mutex.owner_thread->thread_id != + if ((obj_desc->mutex.owner_thread_id != walk_state->thread->thread_id) && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), - (unsigned long)obj_desc->mutex.owner_thread-> - thread_id)); + (unsigned long)obj_desc->mutex.owner_thread_id)); return_ACPI_STATUS(AE_AML_NOT_OWNER); } @@ -301,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Unlink the mutex from the owner's list */ - acpi_ex_unlink_mutex(obj_desc); + acpi_ex_unlink_mutex(obj_desc, walk_state->thread); /* Release the mutex, special case for Global Lock */ @@ -313,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Update the mutex and restore sync_level */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; @@ -368,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/trunk/drivers/acpi/executer/exnames.c b/trunk/drivers/acpi/executer/exnames.c index 308eae52dc05..1ee4fb1175c6 100644 --- a/trunk/drivers/acpi/executer/exnames.c +++ b/trunk/drivers/acpi/executer/exnames.c @@ -177,7 +177,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 0; (index < ACPI_NAME_SIZE) + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); diff --git a/trunk/drivers/acpi/executer/exprep.c b/trunk/drivers/acpi/executer/exprep.c index efe5d4b461a4..a6696621ff1b 100644 --- a/trunk/drivers/acpi/executer/exprep.c +++ b/trunk/drivers/acpi/executer/exprep.c @@ -242,7 +242,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, obj_desc->common_field.bit_length, 0xFFFFFFFF /* Temp until we pass region_length as parameter */ - ); + ); bit_length = byte_alignment * 8; #endif diff --git a/trunk/drivers/acpi/executer/exresop.c b/trunk/drivers/acpi/executer/exresop.c index 09d897b3f6d5..ba761862a599 100644 --- a/trunk/drivers/acpi/executer/exresop.c +++ b/trunk/drivers/acpi/executer/exresop.c @@ -354,7 +354,8 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && (ACPI_GET_OBJECT_TYPE(*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + && ((*stack_ptr)->reference.opcode == + AML_INDEX_OP)) { goto next_operand; } break; diff --git a/trunk/drivers/acpi/executer/exsystem.c b/trunk/drivers/acpi/executer/exsystem.c index 9460baff3032..b2edf620ba89 100644 --- a/trunk/drivers/acpi/executer/exsystem.c +++ b/trunk/drivers/acpi/executer/exsystem.c @@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem") acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); @@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_mutex); @@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { + acpi_status status; + ACPI_FUNCTION_ENTRY(); /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_os_sleep(how_long); /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); - return (AE_OK); + status = acpi_ex_enter_interpreter(); + return (status); } /******************************************************************************* diff --git a/trunk/drivers/acpi/executer/exutils.c b/trunk/drivers/acpi/executer/exutils.c index 6b0aeccbb69b..aea461f3a48c 100644 --- a/trunk/drivers/acpi/executer/exutils.c +++ b/trunk/drivers/acpi/executer/exutils.c @@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ -void acpi_ex_enter_interpreter(void) +acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; @@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void) * * RETURN: None * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void) * * RETURN: none * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. * ******************************************************************************/ diff --git a/trunk/drivers/acpi/hardware/hwsleep.c b/trunk/drivers/acpi/hardware/hwsleep.c index 76c525dc590b..c84b1faba28c 100644 --- a/trunk/drivers/acpi/hardware/hwsleep.c +++ b/trunk/drivers/acpi/hardware/hwsleep.c @@ -152,6 +152,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) #endif + /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state_prep diff --git a/trunk/drivers/acpi/namespace/nseval.c b/trunk/drivers/acpi/namespace/nseval.c index 97b2ac57c16b..26fd0dd6953d 100644 --- a/trunk/drivers/acpi/namespace/nseval.c +++ b/trunk/drivers/acpi/namespace/nseval.c @@ -75,7 +75,7 @@ ACPI_MODULE_NAME("nseval") * MUTEX: Locks interpreter * ******************************************************************************/ -acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; @@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); } else { @@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Function has a strange interface */ diff --git a/trunk/drivers/acpi/namespace/nsinit.c b/trunk/drivers/acpi/namespace/nsinit.c index 33db2241044e..c4ab615f77fe 100644 --- a/trunk/drivers/acpi/namespace/nsinit.c +++ b/trunk/drivers/acpi/namespace/nsinit.c @@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; - acpi_status status = AE_OK; + acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = @@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, /* * Must lock the interpreter before executing AML code */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } /* * Each of these types can contain executable AML code within the diff --git a/trunk/drivers/acpi/namespace/nswalk.c b/trunk/drivers/acpi/namespace/nswalk.c index 280b8357c46c..94eb8f332d94 100644 --- a/trunk/drivers/acpi/namespace/nswalk.c +++ b/trunk/drivers/acpi/namespace/nswalk.c @@ -65,8 +65,10 @@ ACPI_MODULE_NAME("nswalk") * within Scope is returned. * ******************************************************************************/ -struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node - *parent_node, struct acpi_namespace_node +struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, + struct acpi_namespace_node + *parent_node, + struct acpi_namespace_node *child_node) { struct acpi_namespace_node *next_node = NULL; diff --git a/trunk/drivers/acpi/namespace/nsxfeval.c b/trunk/drivers/acpi/namespace/nsxfeval.c index be4f2899de74..8904d0fae6a2 100644 --- a/trunk/drivers/acpi/namespace/nsxfeval.c +++ b/trunk/drivers/acpi/namespace/nsxfeval.c @@ -48,6 +48,7 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -72,8 +73,8 @@ ACPI_MODULE_NAME("nsxfeval") acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer, + struct acpi_object_list * external_params, + struct acpi_buffer * return_buffer, acpi_object_type return_type) { acpi_status status; @@ -142,6 +143,7 @@ acpi_evaluate_object_typed(acpi_handle handle, ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_evaluate_object @@ -168,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle, struct acpi_buffer *return_buffer) { acpi_status status; + acpi_status status2; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; @@ -326,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle, * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ - acpi_ex_enter_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_SUCCESS(status2)) { - /* Remove one reference on the return object (should delete it) */ + /* Remove one reference on the return object (should delete it) */ - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } } cleanup: diff --git a/trunk/drivers/acpi/numa.c b/trunk/drivers/acpi/numa.c index 8fcd6a15517f..4dd0dabe81cb 100644 --- a/trunk/drivers/acpi/numa.c +++ b/trunk/drivers/acpi/numa.c @@ -228,7 +228,7 @@ int __init acpi_numa_init(void) return 0; } -int acpi_get_pxm(acpi_handle h) +int __meminit acpi_get_pxm(acpi_handle h) { unsigned long pxm; acpi_status status; @@ -246,7 +246,7 @@ int acpi_get_pxm(acpi_handle h) } EXPORT_SYMBOL(acpi_get_pxm); -int acpi_get_node(acpi_handle *handle) +int __meminit acpi_get_node(acpi_handle *handle) { int pxm, node = -1; diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index b998340e23d4..c2bed56915e1 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -71,7 +71,6 @@ static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -static struct workqueue_struct *kacpi_notify_wq; static void __init acpi_request_region (struct acpi_generic_address *addr, unsigned int length, char *desc) @@ -138,9 +137,8 @@ acpi_status acpi_os_initialize1(void) return AE_NULL_ENTRY; } kacpid_wq = create_singlethread_workqueue("kacpid"); - kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); BUG_ON(!kacpid_wq); - BUG_ON(!kacpi_notify_wq); + return AE_OK; } @@ -152,7 +150,6 @@ acpi_status acpi_os_terminate(void) } destroy_workqueue(kacpid_wq); - destroy_workqueue(kacpi_notify_wq); return AE_OK; } @@ -604,23 +601,6 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ } static void acpi_os_execute_deferred(struct work_struct *work) -{ - struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - if (!dpc) { - printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); - return; - } - - dpc->function(dpc->context); - kfree(dpc); - - /* Yield cpu to notify thread */ - cond_resched(); - - return; -} - -static void acpi_os_execute_notify(struct work_struct *work) { struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); @@ -657,12 +637,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, acpi_status status = AE_OK; struct acpi_os_dpc *dpc; + ACPI_FUNCTION_TRACE("os_queue_for_execution"); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) - return AE_BAD_PARAMETER; + return_ACPI_STATUS(AE_BAD_PARAMETER); /* * Allocate/initialize DPC structure. Note that this memory will be @@ -680,21 +662,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - if (type == OSL_NOTIFY_HANDLER) { - INIT_WORK(&dpc->work, acpi_os_execute_notify); - if (!queue_work(kacpi_notify_wq, &dpc->work)) { - status = AE_ERROR; - kfree(dpc); - } - } else { - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - if (!queue_work(kacpid_wq, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); - status = AE_ERROR; - kfree(dpc); - } + kfree(dpc); + status = AE_ERROR; } + return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/parser/psopcode.c b/trunk/drivers/acpi/parser/psopcode.c index 9296e86761d7..16d8b6cc3c22 100644 --- a/trunk/drivers/acpi/parser/psopcode.c +++ b/trunk/drivers/acpi/parser/psopcode.c @@ -185,453 +185,459 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ /* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, - ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP, - ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, - ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, - ACPI_TYPE_BUFFER, AML_CLASS_CREATE, - AML_TYPE_CREATE_OBJECT, - AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), + ACPI_TYPE_BUFFER, AML_CLASS_CREATE, + AML_TYPE_CREATE_OBJECT, + AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), /* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, - ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, - AML_TYPE_CREATE_OBJECT, - AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), + ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, + AML_TYPE_CREATE_OBJECT, + AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), /* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, - ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED | AML_DEFER), + ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED | AML_DEFER), /* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R), /* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R), /* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_2T_1R, - AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_2T_1R, + AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), /* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, - ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP, - ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), /* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), /* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R), /* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, - AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, + AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), /* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP, - ARGI_CREATE_DWORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_DWORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, - ARGI_CREATE_WORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_WORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, - ARGI_CREATE_BYTE_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_BYTE_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, - ARGI_CREATE_BIT_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_BIT_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, - AML_TYPE_CONTROL, AML_HAS_ARGS), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, + AML_TYPE_CONTROL, AML_HAS_ARGS), /* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* Prefixed opcodes (Two-byte opcodes with a prefix op) */ /* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), /* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), /* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP, - ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, - AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_FIELD | AML_CREATE), + ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, + AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_FIELD | AML_CREATE), /* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, - AML_FLAGS_EXEC_1A_1T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, + AML_FLAGS_EXEC_1A_1T_0R), /* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), /* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R), /* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), /* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), /* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, - AML_FLAGS_EXEC_3A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, + AML_FLAGS_EXEC_3A_0T_0R), /* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, - ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED | AML_DEFER), + ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED | AML_DEFER), /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, - ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, - ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, - ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP, - ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* Internal opcodes that map to invalid AML opcodes */ /* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), /* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), /* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP, - ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, - AML_HAS_ARGS | AML_CONSTANT), + ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, + AML_HAS_ARGS | AML_CONSTANT), /* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), /* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, - ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, - AML_TYPE_METHOD_CALL, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), + ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, + AML_TYPE_METHOD_CALL, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), /* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, - ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, 0), + ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, 0), /* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP, - ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, - AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, + AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), /* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP, - ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP, - ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, - AML_HAS_ARGS | AML_HAS_RETVAL), + AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, + AML_HAS_ARGS | AML_HAS_RETVAL), /* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, - AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), /* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), /* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), /* ACPI 2.0 opcodes */ /* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), /* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, - ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP, - ARGI_CREATE_QWORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_QWORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP, - ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), /* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, - AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, + AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), /* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, - ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE), /* ACPI 3.0 opcodes */ /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, - AML_FLAGS_EXEC_0A_0T_1R) + AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, + AML_FLAGS_EXEC_0A_0T_1R) /*! [End] no source code translation !*/ }; diff --git a/trunk/drivers/acpi/resources/rscalc.c b/trunk/drivers/acpi/resources/rscalc.c index 0dd2ce8a3475..8c6d3fdec38a 100644 --- a/trunk/drivers/acpi/resources/rscalc.c +++ b/trunk/drivers/acpi/resources/rscalc.c @@ -567,8 +567,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, (*sub_object_list)->string. length + 1); } else { - temp_size_needed += - acpi_ns_get_pathname_length((*sub_object_list)->reference.node); + temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node); } } else { /* diff --git a/trunk/drivers/acpi/resources/rscreate.c b/trunk/drivers/acpi/resources/rscreate.c index 50da494c3ee2..cc48ab05676c 100644 --- a/trunk/drivers/acpi/resources/rscreate.c +++ b/trunk/drivers/acpi/resources/rscreate.c @@ -267,19 +267,16 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * If BIOS erroneously reversed the _PRT source_name and source_index, * then reverse them back. */ - if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != - ACPI_TYPE_INTEGER) { + if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) { if (acpi_gbl_enable_interpreter_slack) { source_name_index = 3; source_index_index = 2; - printk(KERN_WARNING - "ACPI: Handling Garbled _PRT entry\n"); + printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n"); } else { ACPI_ERROR((AE_INFO, - "(PRT[%X].source_index) Need Integer, found %s", - index, - acpi_ut_get_object_type_name - (sub_object_list[3]))); + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(sub_object_list[3]))); return_ACPI_STATUS(AE_BAD_DATA); } } diff --git a/trunk/drivers/acpi/resources/rsdump.c b/trunk/drivers/acpi/resources/rsdump.c index 46da116a4030..de20a5d6decf 100644 --- a/trunk/drivers/acpi/resources/rsdump.c +++ b/trunk/drivers/acpi/resources/rsdump.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsdump") + #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* Local prototypes */ static void acpi_rs_out_string(char *title, char *value); @@ -488,9 +489,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* * Optional resource_source for Address resources */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct - acpi_resource_source, - target)); + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct + acpi_resource_source, + target)); break; default: diff --git a/trunk/drivers/acpi/resources/rsinfo.c b/trunk/drivers/acpi/resources/rsinfo.c index 2c2adb6292c1..7e3c335ab320 100644 --- a/trunk/drivers/acpi/resources/rsinfo.c +++ b/trunk/drivers/acpi/resources/rsinfo.c @@ -142,7 +142,7 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { }; #endif -#endif /* ACPI_FUTURE_USAGE */ +#endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. * Includes size of the descriptor header (1 byte for small descriptors, diff --git a/trunk/drivers/acpi/resources/rslist.c b/trunk/drivers/acpi/resources/rslist.c index ca21e4660c79..a92755c8877d 100644 --- a/trunk/drivers/acpi/resources/rslist.c +++ b/trunk/drivers/acpi/resources/rslist.c @@ -153,9 +153,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Perform the conversion */ - status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union - aml_resource, - aml), + status = acpi_rs_convert_resource_to_aml(resource, + ACPI_CAST_PTR(union + aml_resource, + aml), acpi_gbl_set_resource_dispatch [resource->type]); if (ACPI_FAILURE(status)) { diff --git a/trunk/drivers/acpi/resources/rsmisc.c b/trunk/drivers/acpi/resources/rsmisc.c index c7081afa893a..3b63b561b94e 100644 --- a/trunk/drivers/acpi/resources/rsmisc.c +++ b/trunk/drivers/acpi/resources/rsmisc.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsmisc") + #define INIT_RESOURCE_TYPE(i) i->resource_offset #define INIT_RESOURCE_LENGTH(i) i->aml_offset #define INIT_TABLE_LENGTH(i) i->value @@ -428,7 +429,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Optional resource_source (Index and String) */ aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) + acpi_rs_set_resource_source(aml, + (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; diff --git a/trunk/drivers/acpi/resources/rsutils.c b/trunk/drivers/acpi/resources/rsutils.c index 11c0bd7b9cfd..2442a8f8df57 100644 --- a/trunk/drivers/acpi/resources/rsutils.c +++ b/trunk/drivers/acpi/resources/rsutils.c @@ -353,8 +353,10 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * Zero the entire area of the buffer. */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); diff --git a/trunk/drivers/acpi/resources/rsxface.c b/trunk/drivers/acpi/resources/rsxface.c index f63813a358c5..991f8901498c 100644 --- a/trunk/drivers/acpi/resources/rsxface.c +++ b/trunk/drivers/acpi/resources/rsxface.c @@ -217,6 +217,7 @@ acpi_get_current_resources(acpi_handle device_handle, } ACPI_EXPORT_SYMBOL(acpi_get_current_resources) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -260,6 +261,7 @@ acpi_get_possible_resources(acpi_handle device_handle, ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_set_current_resources @@ -494,6 +496,7 @@ ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) * each resource in the list. * ******************************************************************************/ + acpi_status acpi_walk_resources(acpi_handle device_handle, char *name, diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index bc7e16ec8393..f8c63410bcbf 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -29,6 +29,7 @@ static u32 acpi_suspend_states[] = { [PM_SUSPEND_ON] = ACPI_STATE_S0, [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, [PM_SUSPEND_MEM] = ACPI_STATE_S3, + [PM_SUSPEND_DISK] = ACPI_STATE_S4, [PM_SUSPEND_MAX] = ACPI_STATE_S5 }; @@ -93,6 +94,14 @@ static int acpi_pm_enter(suspend_state_t pm_state) do_suspend_lowlevel(); break; + case PM_SUSPEND_DISK: + if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM) + status = acpi_enter_sleep_state(acpi_state); + break; + case PM_SUSPEND_MAX: + acpi_power_off(); + break; + default: return -EINVAL; } @@ -148,13 +157,12 @@ int acpi_suspend(u32 acpi_state) suspend_state_t states[] = { [1] = PM_SUSPEND_STANDBY, [3] = PM_SUSPEND_MEM, + [4] = PM_SUSPEND_DISK, [5] = PM_SUSPEND_MAX }; if (acpi_state < 6 && states[acpi_state]) return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); return -EINVAL; } @@ -181,49 +189,6 @@ static struct pm_ops acpi_pm_ops = { .finish = acpi_pm_finish, }; -#ifdef CONFIG_SOFTWARE_SUSPEND -static int acpi_hibernation_prepare(void) -{ - return acpi_sleep_prepare(ACPI_STATE_S4); -} - -static int acpi_hibernation_enter(void) -{ - acpi_status status = AE_OK; - unsigned long flags = 0; - - ACPI_FLUSH_CPU_CACHE(); - - local_irq_save(flags); - acpi_enable_wakeup_device(ACPI_STATE_S4); - /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4); - local_irq_restore(flags); - - return ACPI_SUCCESS(status) ? 0 : -EFAULT; -} - -static void acpi_hibernation_finish(void) -{ - acpi_leave_sleep_state(ACPI_STATE_S4); - acpi_disable_wakeup_device(ACPI_STATE_S4); - - /* reset firmware waking vector */ - acpi_set_firmware_waking_vector((acpi_physical_address) 0); - - if (init_8259A_after_S1) { - printk("Broken toshiba laptop -> kicking interrupts\n"); - init_8259A(0); - } -} - -static struct hibernation_ops acpi_hibernation_ops = { - .prepare = acpi_hibernation_prepare, - .enter = acpi_hibernation_enter, - .finish = acpi_hibernation_finish, -}; -#endif /* CONFIG_SOFTWARE_SUSPEND */ - /* * Toshiba fails to preserve interrupts over S1, reinitialization * of 8259 is needed after S1 resume. @@ -262,17 +227,14 @@ int __init acpi_sleep_init(void) sleep_states[i] = 1; printk(" S%d", i); } + if (i == ACPI_STATE_S4) { + if (sleep_states[i]) + acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM; + } } printk(")\n"); pm_set_ops(&acpi_pm_ops); - -#ifdef CONFIG_SOFTWARE_SUSPEND - if (sleep_states[ACPI_STATE_S4]) - hibernation_set_ops(&acpi_hibernation_ops); -#else - sleep_states[ACPI_STATE_S4] = 0; -#endif - return 0; } + diff --git a/trunk/drivers/acpi/sleep/proc.c b/trunk/drivers/acpi/sleep/proc.c index 61f1822cc350..5a76e5be61d5 100644 --- a/trunk/drivers/acpi/sleep/proc.c +++ b/trunk/drivers/acpi/sleep/proc.c @@ -60,7 +60,7 @@ acpi_system_write_sleep(struct file *file, state = simple_strtoul(str, NULL, 0); #ifdef CONFIG_SOFTWARE_SUSPEND if (state == 4) { - error = hibernate(); + error = pm_suspend(PM_SUSPEND_DISK); goto Done; } #endif @@ -349,7 +349,8 @@ acpi_system_write_alarm(struct file *file, end: return_VALUE(result ? result : count); } -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ + extern struct list_head acpi_wakeup_device_list; extern spinlock_t acpi_device_lock; @@ -379,8 +380,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - ldev->bus ? ldev->bus->name : "no-bus", - ldev->bus_id); + ldev->bus ? ldev->bus->name : "no-bus", + ldev->bus_id); seq_printf(seq, "\n"); put_device(ldev); @@ -489,7 +490,7 @@ static u32 rtc_handler(void *context) return ACPI_INTERRUPT_HANDLED; } -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ static int __init acpi_sleep_proc_init(void) { @@ -516,7 +517,7 @@ static int __init acpi_sleep_proc_init(void) entry->proc_fops = &acpi_system_alarm_fops; acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ /* 'wakeup device' [R/W] */ entry = diff --git a/trunk/drivers/acpi/tables/tbfadt.c b/trunk/drivers/acpi/tables/tbfadt.c index 1285e91474fb..1db833eb2417 100644 --- a/trunk/drivers/acpi/tables/tbfadt.c +++ b/trunk/drivers/acpi/tables/tbfadt.c @@ -334,8 +334,7 @@ static void acpi_tb_convert_fadt(void) (acpi_gbl_FADT.xpm1a_event_block.address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; /* The PM1B register block is optional, ignore if not present */ @@ -345,8 +344,7 @@ static void acpi_tb_convert_fadt(void) (acpi_gbl_FADT.xpm1b_event_block. address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; } diff --git a/trunk/drivers/acpi/tables/tbxface.c b/trunk/drivers/acpi/tables/tbxface.c index 5b302c4e293f..417ef5fa7666 100644 --- a/trunk/drivers/acpi/tables/tbxface.c +++ b/trunk/drivers/acpi/tables/tbxface.c @@ -201,7 +201,6 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(AE_OK); } - /******************************************************************************* * * FUNCTION: acpi_load_table @@ -263,7 +262,7 @@ ACPI_EXPORT_SYMBOL(acpi_load_table) acpi_status acpi_get_table_header(char *signature, acpi_native_uint instance, - struct acpi_table_header * out_table_header) + struct acpi_table_header *out_table_header) { acpi_native_uint i; acpi_native_uint j; @@ -322,6 +321,7 @@ acpi_get_table_header(char *signature, ACPI_EXPORT_SYMBOL(acpi_get_table_header) + /****************************************************************************** * * FUNCTION: acpi_unload_table_id @@ -346,11 +346,11 @@ acpi_status acpi_unload_table_id(acpi_owner_id id) continue; } /* - * Delete all namespace objects owned by this table. Note that these - * objects can appear anywhere in the namespace by virtue of the AML - * "Scope" operator. Thus, we need to track ownership by an ID, not - * simply a position within the hierarchy - */ + * Delete all namespace objects owned by this table. Note that these + * objects can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ acpi_tb_delete_namespace_by_owner(i); status = acpi_tb_release_owner_id(i); acpi_tb_set_table_loaded_flag(i, FALSE); @@ -376,7 +376,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) *****************************************************************************/ acpi_status acpi_get_table(char *signature, - acpi_native_uint instance, struct acpi_table_header **out_table) + acpi_native_uint instance, struct acpi_table_header ** out_table) { acpi_native_uint i; acpi_native_uint j; diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index 1ada017d01ef..589b98b7b216 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -59,6 +59,8 @@ #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 #define ACPI_THERMAL_NOTIFY_HOT 0xF1 #define ACPI_THERMAL_MODE_ACTIVE 0x00 +#define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_MODE_CRITICAL 0xff #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" #define ACPI_THERMAL_MAX_ACTIVE 10 @@ -84,6 +86,9 @@ static int acpi_thermal_resume(struct acpi_device *device); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); +static ssize_t acpi_thermal_write_trip_points(struct file *, + const char __user *, size_t, + loff_t *); static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); static ssize_t acpi_thermal_write_cooling_mode(struct file *, const char __user *, size_t, @@ -162,6 +167,7 @@ struct acpi_thermal { unsigned long temperature; unsigned long last_temperature; unsigned long polling_frequency; + u8 cooling_mode; volatile u8 zombie; struct acpi_thermal_flags flags; struct acpi_thermal_state state; @@ -187,6 +193,7 @@ static const struct file_operations acpi_thermal_temp_fops = { static const struct file_operations acpi_thermal_trip_fops = { .open = acpi_thermal_trip_open_fs, .read = seq_read, + .write = acpi_thermal_write_trip_points, .llseek = seq_lseek, .release = single_release, }; @@ -290,6 +297,11 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) if (ACPI_FAILURE(status)) return -ENODEV; + tz->cooling_mode = mode; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", + mode ? "passive" : "active")); + return 0; } @@ -877,6 +889,67 @@ static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); } +static ssize_t +acpi_thermal_write_trip_points(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file *m = file->private_data; + struct acpi_thermal *tz = m->private; + + char *limit_string; + int num, critical, hot, passive; + int *active; + int i = 0; + + + limit_string = kzalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL); + if (!limit_string) + return -ENOMEM; + + active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); + if (!active) { + kfree(limit_string); + return -ENOMEM; + } + + if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) { + count = -EINVAL; + goto end; + } + + if (copy_from_user(limit_string, buffer, count)) { + count = -EFAULT; + goto end; + } + + limit_string[count] = '\0'; + + num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &critical, &hot, &passive, + &active[0], &active[1], &active[2], &active[3], &active[4], + &active[5], &active[6], &active[7], &active[8], + &active[9]); + if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) { + count = -EINVAL; + goto end; + } + + tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical); + tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot); + tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive); + for (i = 0; i < num - 3; i++) { + if (!(tz->trips.active[i].flags.valid)) + break; + tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]); + } + + end: + kfree(active); + kfree(limit_string); + return count; +} + static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) { struct acpi_thermal *tz = seq->private; @@ -885,10 +958,15 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) if (!tz) goto end; - if (!tz->flags.cooling_mode) + if (!tz->flags.cooling_mode) { seq_puts(seq, "\n"); + } + + if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL) + seq_printf(seq, "cooling mode: critical\n"); else - seq_puts(seq, "0 - Active; 1 - Passive\n"); + seq_printf(seq, "cooling mode: %s\n", + tz->cooling_mode ? "passive" : "active"); end: return 0; @@ -1145,6 +1223,28 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); if (!result) tz->flags.cooling_mode = 1; + else { + /* Oh,we have not _SCP method. + Generally show cooling_mode by _ACx, _PSV,spec 12.2 */ + tz->flags.cooling_mode = 0; + if (tz->trips.active[0].flags.valid + && tz->trips.passive.flags.valid) { + if (tz->trips.passive.temperature > + tz->trips.active[0].temperature) + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + else + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if (!tz->trips.active[0].flags.valid + && tz->trips.passive.flags.valid) { + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if (tz->trips.active[0].flags.valid + && !tz->trips.passive.flags.valid) { + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + } else { + /* _ACx and _PSV are optional, but _CRT is required */ + tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL; + } + } /* Get default polling frequency [_TZP] (optional) */ if (tzp) diff --git a/trunk/drivers/acpi/utilities/utalloc.c b/trunk/drivers/acpi/utilities/utalloc.c index 6e56d5f7c43a..55a764807499 100644 --- a/trunk/drivers/acpi/utilities/utalloc.c +++ b/trunk/drivers/acpi/utilities/utalloc.c @@ -107,6 +107,7 @@ acpi_status acpi_ut_create_caches(void) if (ACPI_FAILURE(status)) { return (status); } + #ifdef ACPI_DBG_TRACK_ALLOCATIONS /* Memory allocation lists */ diff --git a/trunk/drivers/acpi/utilities/utcache.c b/trunk/drivers/acpi/utilities/utcache.c index 285a0f531760..870f6edeb5f2 100644 --- a/trunk/drivers/acpi/utilities/utcache.c +++ b/trunk/drivers/acpi/utilities/utcache.c @@ -45,6 +45,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utcache") + #ifdef ACPI_USE_LOCAL_CACHE /******************************************************************************* * @@ -63,7 +64,7 @@ ACPI_MODULE_NAME("utcache") acpi_status acpi_os_create_cache(char *cache_name, u16 object_size, - u16 max_depth, struct acpi_memory_list ** return_cache) + u16 max_depth, struct acpi_memory_list **return_cache) { struct acpi_memory_list *cache; diff --git a/trunk/drivers/acpi/utilities/utcopy.c b/trunk/drivers/acpi/utilities/utcopy.c index 4c1e00874dff..84d529db0a66 100644 --- a/trunk/drivers/acpi/utilities/utcopy.c +++ b/trunk/drivers/acpi/utilities/utcopy.c @@ -814,9 +814,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, /* * Create the object array */ - target_object->package.elements = - ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package. - count + 1) * sizeof(void *)); + target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *)); if (!target_object->package.elements) { status = AE_NO_MEMORY; goto error_exit; diff --git a/trunk/drivers/acpi/utilities/utdebug.c b/trunk/drivers/acpi/utilities/utdebug.c index c7e128e5369b..61ad4f2daee2 100644 --- a/trunk/drivers/acpi/utilities/utdebug.c +++ b/trunk/drivers/acpi/utilities/utdebug.c @@ -45,6 +45,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdebug") + #ifdef ACPI_DEBUG_OUTPUT static acpi_thread_id acpi_gbl_prev_thread_id; static char *acpi_gbl_fn_entry_str = "----Entry"; @@ -180,8 +181,7 @@ acpi_ut_debug_print(u32 requested_debug_level, if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf ("\n**** Context Switch from TID %lX to TID %lX ****\n\n", - (unsigned long)acpi_gbl_prev_thread_id, - (unsigned long)thread_id); + (unsigned long)acpi_gbl_prev_thread_id, (unsigned long)thread_id); } acpi_gbl_prev_thread_id = thread_id; diff --git a/trunk/drivers/acpi/utilities/utdelete.c b/trunk/drivers/acpi/utilities/utdelete.c index f777cebdc46d..673a0caa4073 100644 --- a/trunk/drivers/acpi/utilities/utdelete.c +++ b/trunk/drivers/acpi/utilities/utdelete.c @@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) acpi_os_delete_mutex(object->mutex.os_mutex); acpi_gbl_global_lock_mutex = NULL; } else { - acpi_ex_unlink_mutex(object); acpi_os_delete_mutex(object->mutex.os_mutex); } break; diff --git a/trunk/drivers/acpi/utilities/utglobal.c b/trunk/drivers/acpi/utilities/utglobal.c index 1621655d6e2b..af33358a964b 100644 --- a/trunk/drivers/acpi/utilities/utglobal.c +++ b/trunk/drivers/acpi/utilities/utglobal.c @@ -55,10 +55,12 @@ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) * Static global variable initialization. * ******************************************************************************/ + /* * We want the debug switches statically initialized so they * are already set when the debugger is entered. */ + /* Debug switch - level and trace mask */ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; @@ -733,5 +735,5 @@ void acpi_ut_init_globals(void) } ACPI_EXPORT_SYMBOL(acpi_dbg_level) - ACPI_EXPORT_SYMBOL(acpi_dbg_layer) - ACPI_EXPORT_SYMBOL(acpi_gpe_count) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_gpe_count) diff --git a/trunk/drivers/acpi/utilities/utmisc.c b/trunk/drivers/acpi/utilities/utmisc.c index 2d19f71e9cfa..50133fffe420 100644 --- a/trunk/drivers/acpi/utilities/utmisc.c +++ b/trunk/drivers/acpi/utilities/utmisc.c @@ -802,8 +802,9 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) valid_digits++; - if (sign_of0x && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { /* * This is to_integer operation case. * No any restrictions for string-to-integer conversion, @@ -1048,7 +1049,6 @@ acpi_ut_exception(char *module_name, acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } - EXPORT_SYMBOL(acpi_ut_exception); void ACPI_INTERNAL_VAR_XFACE diff --git a/trunk/drivers/acpi/utilities/utmutex.c b/trunk/drivers/acpi/utilities/utmutex.c index 4820bc86d1f5..cbad2ef5987d 100644 --- a/trunk/drivers/acpi/utilities/utmutex.c +++ b/trunk/drivers/acpi/utilities/utmutex.c @@ -244,7 +244,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX attempting to acquire Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, @@ -252,7 +252,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) if (ACPI_SUCCESS(status)) { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX acquired Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); acpi_gbl_mutex_info[mutex_id].use_count++; @@ -260,7 +260,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) } else { ACPI_EXCEPTION((AE_INFO, status, "Thread %lX could not acquire Mutex [%X]", - (unsigned long)this_thread_id, mutex_id)); + (unsigned long) this_thread_id, mutex_id)); } return (status); @@ -287,7 +287,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) this_thread_id = acpi_os_get_thread_id(); ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX releasing Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); if (mutex_id > ACPI_MAX_MUTEX) { diff --git a/trunk/drivers/acpi/utilities/utresrc.c b/trunk/drivers/acpi/utilities/utresrc.c index cbbd3315a1e2..e8fe1ba6cc24 100644 --- a/trunk/drivers/acpi/utilities/utresrc.c +++ b/trunk/drivers/acpi/utilities/utresrc.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utresrc") + #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. diff --git a/trunk/drivers/acpi/utilities/utxface.c b/trunk/drivers/acpi/utilities/utxface.c index e9a57806cd34..de3276f4f468 100644 --- a/trunk/drivers/acpi/utilities/utxface.c +++ b/trunk/drivers/acpi/utilities/utxface.c @@ -337,6 +337,7 @@ acpi_status acpi_terminate(void) } ACPI_EXPORT_SYMBOL(acpi_terminate) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -469,6 +470,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) #endif /* ACPI_FUTURE_USAGE */ + /***************************************************************************** * * FUNCTION: acpi_purge_cached_objects diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index f031b8732330..45dbdc14915f 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -3,7 +3,6 @@ # menu "Serial ATA (prod) and Parallel ATA (experimental) drivers" - depends on HAS_IOMEM config ATA tristate "ATA device support" @@ -436,7 +435,7 @@ config PATA_OPTIDMA help This option enables DMA/PIO support for the later OPTi controllers found on some old motherboards and in some - laptops. + latops If unsure, say N. diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c index cb3eab6e379d..03a0acff6cfa 100644 --- a/trunk/drivers/ata/libata-acpi.c +++ b/trunk/drivers/ata/libata-acpi.c @@ -489,7 +489,8 @@ static void taskfile_load_raw(struct ata_port *ap, /* convert gtf to tf */ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ - tf.protocol = ATA_PROT_NODATA; + tf.protocol = atadev->class == ATA_DEV_ATAPI ? + ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA; tf.feature = gtf->tfa[0]; /* 0x1f1 */ tf.nsect = gtf->tfa[1]; /* 0x1f2 */ tf.lbal = gtf->tfa[2]; /* 0x1f3 */ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 4595d1f8cf60..a7950885d18e 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -895,7 +895,6 @@ static u64 ata_read_native_max_address(struct ata_device *dev) /** * ata_set_native_max_address_ext - LBA48 native max set * @dev: Device to query - * @new_sectors: new max sectors value to set for the device * * Perform an LBA48 size set max upon the device in question. Return the * actual LBA48 size or zero if the command fails. @@ -933,7 +932,6 @@ static u64 ata_set_native_max_address_ext(struct ata_device *dev, u64 new_sector /** * ata_set_native_max_address - LBA28 native max set * @dev: Device to query - * @new_sectors: new max sectors value to set for the device * * Perform an LBA28 size set max upon the device in question. Return the * actual LBA28 size or zero if the command fails. @@ -1318,7 +1316,7 @@ void ata_port_flush_task(struct ata_port *ap) spin_unlock_irqrestore(ap->lock, flags); DPRINTK("flush #1\n"); - cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */ + flush_workqueue(ata_wq); /* * At this point, if a task is running, it's guaranteed to see @@ -1329,7 +1327,7 @@ void ata_port_flush_task(struct ata_port *ap) if (ata_msg_ctl(ap)) ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n", __FUNCTION__); - cancel_work_sync(&ap->port_task.work); + flush_workqueue(ata_wq); } spin_lock_irqsave(ap->lock, flags); @@ -6477,9 +6475,9 @@ void ata_port_detach(struct ata_port *ap) /* Flush hotplug task. The sequence is similar to * ata_port_flush_task(). */ - cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */ + flush_workqueue(ata_aux_wq); cancel_delayed_work(&ap->hotplug_task); - cancel_work_sync(&ap->hotplug_task.work); + flush_workqueue(ata_aux_wq); skip_eh: /* remove the associated SCSI host */ diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c index 11245e331f77..75dc84797ff3 100644 --- a/trunk/drivers/ata/pata_pcmcia.c +++ b/trunk/drivers/ata/pata_pcmcia.c @@ -357,7 +357,6 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), diff --git a/trunk/drivers/ata/pata_qdi.c b/trunk/drivers/ata/pata_qdi.c index fb8c9e14b8d4..27685ce63ceb 100644 --- a/trunk/drivers/ata/pata_qdi.c +++ b/trunk/drivers/ata/pata_qdi.c @@ -375,7 +375,7 @@ static __init int qdi_init(void) res = inb(port + 3); if (res & 1) { /* Single channel mode */ - if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0) + if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04)) ct++; } else { /* Dual channel mode */ diff --git a/trunk/drivers/ata/pata_scc.c b/trunk/drivers/ata/pata_scc.c index 203f463ac39f..5df354d573e8 100644 --- a/trunk/drivers/ata/pata_scc.c +++ b/trunk/drivers/ata/pata_scc.c @@ -1142,14 +1142,14 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; unsigned int board_idx = (unsigned int) ent->driver_data; const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL }; - struct ata_host *host; + struct device *dev = &pdev->dev; int rc; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1); + host = ata_port_alloc_pinfo(&pdev->dev, ppi, 1); if (!host) return -ENOMEM; diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c index a097595d4dc7..e2e795e58236 100644 --- a/trunk/drivers/ata/sata_nv.c +++ b/trunk/drivers/ata/sata_nv.c @@ -257,8 +257,6 @@ static void nv_adma_port_stop(struct ata_port *ap); static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); static int nv_adma_port_resume(struct ata_port *ap); #endif -static void nv_adma_freeze(struct ata_port *ap); -static void nv_adma_thaw(struct ata_port *ap); static void nv_adma_error_handler(struct ata_port *ap); static void nv_adma_host_stop(struct ata_host *host); static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); @@ -446,8 +444,8 @@ static const struct ata_port_operations nv_adma_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = nv_adma_qc_prep, .qc_issue = nv_adma_qc_issue, - .freeze = nv_adma_freeze, - .thaw = nv_adma_thaw, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, .error_handler = nv_adma_error_handler, .post_internal_cmd = nv_adma_post_internal_cmd, .data_xfer = ata_data_xfer, @@ -817,16 +815,8 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) u16 status; u32 gen_ctl; u32 notifier, notifier_error; - - /* if ADMA is disabled, use standard ata interrupt handler */ - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { - u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) - >> (NV_INT_PORT_SHIFT * i); - handled += nv_host_intr(ap, irq_stat); - continue; - } - /* if in ATA register mode, check for standard interrupts */ + /* if in ATA register mode, use standard ata interrupt handler */ if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) >> (NV_INT_PORT_SHIFT * i); @@ -836,6 +826,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) command is active, to prevent losing interrupts. */ irq_stat |= NV_INT_DEV; handled += nv_host_intr(ap, irq_stat); + continue; } notifier = readl(mmio + NV_ADMA_NOTIFIER); @@ -921,77 +912,22 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static void nv_adma_freeze(struct ata_port *ap) -{ - struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = pp->ctl_block; - u16 tmp; - - nv_ck804_freeze(ap); - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) - return; - - /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), - ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); - - /* Disable interrupt */ - tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), - mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ -} - -static void nv_adma_thaw(struct ata_port *ap) -{ - struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = pp->ctl_block; - u16 tmp; - - nv_ck804_thaw(ap); - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) - return; - - /* Enable interrupt */ - tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), - mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ -} - static void nv_adma_irq_clear(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; void __iomem *mmio = pp->ctl_block; - u32 notifier_clears[2]; - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { - ata_bmdma_irq_clear(ap); - return; - } - - /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), - ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); + u16 status = readw(mmio + NV_ADMA_STAT); + u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); + u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; /* clear ADMA status */ - writew(0xffff, mmio + NV_ADMA_STAT); - - /* clear notifiers - note both ports need to be written with - something even though we are only clearing on one */ - if (ap->port_no == 0) { - notifier_clears[0] = 0xFFFFFFFF; - notifier_clears[1] = 0; - } else { - notifier_clears[0] = 0; - notifier_clears[1] = 0xFFFFFFFF; - } - pp = ap->host->ports[0]->private_data; - writel(notifier_clears[0], pp->notifier_clear_block); - pp = ap->host->ports[1]->private_data; - writel(notifier_clears[1], pp->notifier_clear_block); + writew(status, mmio + NV_ADMA_STAT); + writel(notifier | notifier_error, + pp->notifier_clear_block); + + /** clear legacy status */ + iowrite8(ioread8(dma_stat_addr), dma_stat_addr); } static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/trunk/drivers/ata/sata_promise.c b/trunk/drivers/ata/sata_promise.c index 3a7d9b5332af..f56549b90aa6 100644 --- a/trunk/drivers/ata/sata_promise.c +++ b/trunk/drivers/ata/sata_promise.c @@ -45,7 +45,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.07" +#define DRV_VERSION "2.05" enum { @@ -653,8 +653,6 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, qc->err_mask |= ac_err_mask; pdc_reset_port(ap); - - ata_port_abort(ap); } static inline unsigned int pdc_host_intr( struct ata_port *ap, @@ -926,7 +924,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e struct ata_host *host; void __iomem *base; int n_ports, i, rc; - int is_sataii_tx4; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -965,23 +962,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } host->iomap = pcim_iomap_table(pdev); - is_sataii_tx4 = 0; - if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) { - is_sataii_tx4 = 1; - dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n"); - } - for (i = 0; i < host->n_ports; i++) { - static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; - int ata_nr; - - ata_nr = i; - if (is_sataii_tx4) - ata_nr = sataii_tx4_port_remap[i]; - + for (i = 0; i < host->n_ports; i++) pdc_ata_setup_port(host->ports[i], - base + 0x200 + ata_nr * 0x80, - base + 0x400 + ata_nr * 0x100); - } + base + 0x200 + i * 0x80, + base + 0x400 + i * 0x100); /* initialize adapter */ pdc_host_init(host); diff --git a/trunk/drivers/ata/sata_via.c b/trunk/drivers/ata/sata_via.c index 939c9246fdd1..305ab7c68ca5 100644 --- a/trunk/drivers/ata/sata_via.c +++ b/trunk/drivers/ata/sata_via.c @@ -93,10 +93,6 @@ static struct pci_driver svia_pci_driver = { .name = DRV_NAME, .id_table = svia_pci_tbl, .probe = svia_init_one, -#ifdef CONFIG_PM - .suspend = ata_pci_device_suspend, - .resume = ata_pci_device_resume, -#endif .remove = ata_pci_remove_one, }; @@ -116,10 +112,6 @@ static struct scsi_host_template svia_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations vt6420_sata_ops = { diff --git a/trunk/drivers/auxdisplay/Kconfig b/trunk/drivers/auxdisplay/Kconfig index 2e18a63ead36..0300e7f54cc4 100644 --- a/trunk/drivers/auxdisplay/Kconfig +++ b/trunk/drivers/auxdisplay/Kconfig @@ -6,7 +6,6 @@ # menu "Auxiliary Display support" - depends on PARPORT config KS0108 tristate "KS0108 LCD Controller" diff --git a/trunk/drivers/base/devres.c b/trunk/drivers/base/devres.c index e1c0730a3b99..e177c9533b6c 100644 --- a/trunk/drivers/base/devres.c +++ b/trunk/drivers/base/devres.c @@ -101,6 +101,19 @@ static void add_dr(struct device *dev, struct devres_node *node) list_add_tail(&node->entry, &dev->devres_head); } +/** + * devres_alloc - Allocate device resource data + * @release: Release function devres will be associated with + * @size: Allocation size + * @gfp: Allocation flags + * + * allocate devres of @size bytes. The allocated area is zeroed, then + * associated with @release. The returned pointer can be passed to + * other devres_*() functions. + * + * RETURNS: + * Pointer to allocated devres on success, NULL on failure. + */ #ifdef CONFIG_DEBUG_DEVRES void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp, const char *name) @@ -115,19 +128,6 @@ void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp, } EXPORT_SYMBOL_GPL(__devres_alloc); #else -/** - * devres_alloc - Allocate device resource data - * @release: Release function devres will be associated with - * @size: Allocation size - * @gfp: Allocation flags - * - * Allocate devres of @size bytes. The allocated area is zeroed, then - * associated with @release. The returned pointer can be passed to - * other devres_*() functions. - * - * RETURNS: - * Pointer to allocated devres on success, NULL on failure. - */ void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp) { struct devres *dr; @@ -416,7 +416,7 @@ static int release_nodes(struct device *dev, struct list_head *first, } /** - * devres_release_all - Release all managed resources + * devres_release_all - Release all resources * @dev: Device to release resources for * * Release all resources associated with @dev. This function is @@ -600,7 +600,7 @@ static int devm_kzalloc_match(struct device *dev, void *res, void *data) } /** - * devm_kzalloc - Resource-managed kzalloc + * devm_kzalloc - Managed kzalloc * @dev: Device to allocate memory for * @size: Allocation size * @gfp: Allocation gfp flags @@ -628,7 +628,7 @@ void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) EXPORT_SYMBOL_GPL(devm_kzalloc); /** - * devm_kfree - Resource-managed kfree + * devm_kfree - Managed kfree * @dev: Device this memory belongs to * @p: Memory to free * diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index 869ff8c00146..eb84d9d44645 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -360,7 +360,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * This function creates a simple platform device that requires minimal * resource and memory management. Canned release function freeing * memory allocated for the device allows drivers using such devices - * to be unloaded without waiting for the last reference to the device + * to be unloaded iwithout waiting for the last reference to the device * to be dropped. * * This interface is primarily intended for use with legacy drivers diff --git a/trunk/drivers/base/topology.c b/trunk/drivers/base/topology.c index 8d8cdfec6529..067a9e8bc377 100644 --- a/trunk/drivers/base/topology.c +++ b/trunk/drivers/base/topology.c @@ -126,13 +126,10 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: rc = topology_add_dev(cpu); break; case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: - case CPU_DEAD_FROZEN: topology_remove_dev(cpu); break; } diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index b4c8319138b2..17ee97f3a99b 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -444,6 +444,8 @@ config CDROM_PKTCDVD_WCACHE this option is dangerous unless the CD-RW media is known good, as we don't do deferred write error handling yet. +source "drivers/s390/block/Kconfig" + config ATA_OVER_ETH tristate "ATA over Ethernet support" depends on NET @@ -451,8 +453,6 @@ config ATA_OVER_ETH This driver provides Support for ATA over Ethernet block devices like the Coraid EtherDrive (R) Storage Blade. -source "drivers/s390/block/Kconfig" - endmenu endif diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 18cdd8c77626..af6d7274a7cc 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -243,13 +243,17 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, transfer_result = lo_do_transfer(lo, WRITE, page, offset, bvec->bv_page, bv_offs, size, IV); if (unlikely(transfer_result)) { + char *kaddr; + /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); - zero_user_page(page, offset, size, KM_USER0); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, size); + kunmap_atomic(kaddr, KM_USER0); } flush_dcache_page(page); ret = aops->commit_write(file, page, offset, diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 069ae39a9cd9..090796bef78f 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -366,25 +366,20 @@ static struct disk_attribute pid_attr = { .show = pid_show, }; -static int nbd_do_it(struct nbd_device *lo) +static void nbd_do_it(struct nbd_device *lo) { struct request *req; - int ret; BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); - if (ret) { - printk(KERN_ERR "nbd: sysfs_create_file failed!"); - return ret; - } + sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr); - return 0; + return; } static void nbd_clear_que(struct nbd_device *lo) @@ -574,9 +569,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, case NBD_DO_IT: if (!lo->file) return -EINVAL; - error = nbd_do_it(lo); - if (error) - return error; + nbd_do_it(lo); /* on return tidy up in case we have a signal */ /* Forcibly shutdown the socket causing all listeners * to error diff --git a/trunk/drivers/block/rd.c b/trunk/drivers/block/rd.c index a1512da32410..43d4ebcb3b44 100644 --- a/trunk/drivers/block/rd.c +++ b/trunk/drivers/block/rd.c @@ -151,7 +151,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page, } /* - * ->writepage to the blockdev's mapping has to redirty the page so that the + * ->writepage to the the blockdev's mapping has to redirty the page so that the * VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM * won't try to (pointlessly) write the page again for a while. * diff --git a/trunk/drivers/bluetooth/hci_ldisc.c b/trunk/drivers/bluetooth/hci_ldisc.c index 6055b9c0ac0f..0f4203b499af 100644 --- a/trunk/drivers/bluetooth/hci_ldisc.c +++ b/trunk/drivers/bluetooth/hci_ldisc.c @@ -307,9 +307,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) if (hu) { struct hci_dev *hdev = hu->hdev; - - if (hdev) - hci_uart_close(hdev); + hci_uart_close(hdev); if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { hu->proto->close(hu); @@ -475,18 +473,12 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, tty->low_latency = 1; } else return -EBUSY; - break; case HCIUARTGETPROTO: if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) return hu->proto->id; return -EUNATCH; - case HCIUARTGETDEVICE: - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) - return hu->hdev->id; - return -EUNATCH; - default: err = n_tty_ioctl(tty, file, cmd, arg); break; diff --git a/trunk/drivers/bluetooth/hci_uart.h b/trunk/drivers/bluetooth/hci_uart.h index 1097ce72393f..b250e6789dee 100644 --- a/trunk/drivers/bluetooth/hci_uart.h +++ b/trunk/drivers/bluetooth/hci_uart.h @@ -28,9 +28,8 @@ #endif /* Ioctls */ -#define HCIUARTSETPROTO _IOW('U', 200, int) -#define HCIUARTGETPROTO _IOR('U', 201, int) -#define HCIUARTGETDEVICE _IOR('U', 202, int) +#define HCIUARTSETPROTO _IOW('U', 200, int) +#define HCIUARTGETPROTO _IOR('U', 201, int) /* UART protocols */ #define HCI_UART_MAX_PROTO 4 diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index abcafac64738..1e32fb834eb8 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -6,7 +6,6 @@ menu "Character devices" config VT bool "Virtual terminal" if EMBEDDED - depends on !S390 select INPUT default y if !VIOCONS ---help--- @@ -82,7 +81,6 @@ config VT_HW_CONSOLE_BINDING config SERIAL_NONSTANDARD bool "Non-standard serial port support" - depends on HAS_IOMEM ---help--- Say Y here if you have any non-standard serial boards -- boards which aren't supported using the standard "dumb" serial driver. @@ -633,8 +631,7 @@ config HVC_CONSOLE config HVC_ISERIES bool "iSeries Hypervisor Virtual Console support" - depends on PPC_ISERIES - default y + depends on PPC_ISERIES && !VIOCONS select HVC_DRIVER help iSeries machines support a hypervisor virtual console. @@ -767,7 +764,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 + depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -815,7 +812,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 + depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -860,7 +857,6 @@ config COBALT_LCD config DTLK tristate "Double Talk PC internal speech card support" - depends on ISA help This driver is for the DoubleTalk PC, a speech synthesizer manufactured by RC Systems (). It is also @@ -1046,7 +1042,7 @@ config HPET_MMAP config HANGCHECK_TIMER tristate "Hangcheck timer" - depends on X86 || IA64 || PPC64 || S390 + depends on X86 || IA64 || PPC64 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system @@ -1081,7 +1077,5 @@ config DEVPORT depends on ISA || PCI default y -source "drivers/s390/char/Kconfig" - endmenu diff --git a/trunk/drivers/char/drm/drm_dma.c b/trunk/drivers/char/drm/drm_dma.c index 32ed19c9ec1c..892db7096986 100644 --- a/trunk/drivers/char/drm/drm_dma.c +++ b/trunk/drivers/char/drm/drm_dma.c @@ -65,7 +65,7 @@ int drm_dma_setup(drm_device_t * dev) * \param dev DRM device. * * Free all pages associated with DMA buffers, the buffers and pages lists, and - * finally the drm_device::dma structure itself. + * finally the the drm_device::dma structure itself. */ void drm_dma_takedown(drm_device_t * dev) { diff --git a/trunk/drivers/char/drm/drm_vm.c b/trunk/drivers/char/drm/drm_vm.c index b5c5b9fa84c3..35540cfb43dd 100644 --- a/trunk/drivers/char/drm/drm_vm.c +++ b/trunk/drivers/char/drm/drm_vm.c @@ -157,7 +157,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * \param address access address. * \return pointer to the page structure. * - * Get the mapping, find the real physical page to map, get the page, and + * Get the the mapping, find the real physical page to map, get the page, and * return it. */ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, diff --git a/trunk/drivers/char/drm/r300_reg.h b/trunk/drivers/char/drm/r300_reg.h index ecda760ae8c0..a881f96c983e 100644 --- a/trunk/drivers/char/drm/r300_reg.h +++ b/trunk/drivers/char/drm/r300_reg.h @@ -293,7 +293,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 # define R300_PVS_CNTL_1_POS_END_SHIFT 10 # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 -/* Addresses are relative to the vertex program parameters area. */ +/* Addresses are relative the the vertex program parameters area. */ #define R300_VAP_PVS_CNTL_2 0x22D4 # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 diff --git a/trunk/drivers/char/genrtc.c b/trunk/drivers/char/genrtc.c index 9e1fc02967ff..49f914e79216 100644 --- a/trunk/drivers/char/genrtc.c +++ b/trunk/drivers/char/genrtc.c @@ -12,7 +12,7 @@ * * This driver allows use of the real time clock (built into * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/driver/rtc + * interface supporting various ioctl() and also the /proc/dev/rtc * pseudo-file for status information. * * The ioctls can be used to set the interrupt behaviour where @@ -377,7 +377,7 @@ static int gen_rtc_release(struct inode *inode, struct file *file) #ifdef CONFIG_PROC_FS /* - * Info exported via "/proc/driver/rtc". + * Info exported via "/proc/rtc". */ static int gen_rtc_proc_output(char *buf) diff --git a/trunk/drivers/char/hw_random/Kconfig b/trunk/drivers/char/hw_random/Kconfig index 7cda04b33534..5f3acd8e64b8 100644 --- a/trunk/drivers/char/hw_random/Kconfig +++ b/trunk/drivers/char/hw_random/Kconfig @@ -91,17 +91,3 @@ config HW_RANDOM_OMAP module will be called omap-rng. If unsure, say Y. - -config HW_RANDOM_PASEMI - tristate "PA Semi HW Random Number Generator support" - depends on HW_RANDOM && PPC_PASEMI - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on PA6T-1682M processor. - - To compile this driver as a module, choose M here: the - module will be called pasemi-rng. - - If unsure, say Y. - diff --git a/trunk/drivers/char/hw_random/Makefile b/trunk/drivers/char/hw_random/Makefile index c8b7300e2fb1..c41fa19454e3 100644 --- a/trunk/drivers/char/hw_random/Makefile +++ b/trunk/drivers/char/hw_random/Makefile @@ -10,4 +10,3 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o -obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o diff --git a/trunk/drivers/char/hw_random/pasemi-rng.c b/trunk/drivers/char/hw_random/pasemi-rng.c deleted file mode 100644 index fa6040b6c8f2..000000000000 --- a/trunk/drivers/char/hw_random/pasemi-rng.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2006-2007 PA Semi, Inc - * - * Maintained by: Olof Johansson - * - * Driver for the PWRficient onchip rng - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -#define SDCRNG_CTL_REG 0x00 -#define SDCRNG_CTL_FVLD_M 0x0000f000 -#define SDCRNG_CTL_FVLD_S 12 -#define SDCRNG_CTL_KSZ 0x00000800 -#define SDCRNG_CTL_RSRC_CRG 0x00000010 -#define SDCRNG_CTL_RSRC_RRG 0x00000000 -#define SDCRNG_CTL_CE 0x00000004 -#define SDCRNG_CTL_RE 0x00000002 -#define SDCRNG_CTL_DR 0x00000001 -#define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG) -#define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG) -#define SDCRNG_VAL_REG 0x20 - -#define MODULE_NAME "pasemi_rng" - -static int pasemi_rng_data_present(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - - return (in_le32(rng_regs + SDCRNG_CTL_REG) - & SDCRNG_CTL_FVLD_M) ? 1 : 0; -} - -static int pasemi_rng_data_read(struct hwrng *rng, u32 *data) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - *data = in_le32(rng_regs + SDCRNG_VAL_REG); - return 4; -} - -static int pasemi_rng_init(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - u32 ctl; - - ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ; - out_le32(rng_regs + SDCRNG_CTL_REG, ctl); - out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR); - - return 0; -} - -static void pasemi_rng_cleanup(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - u32 ctl; - - ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE; - out_le32(rng_regs + SDCRNG_CTL_REG, - in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl); -} - -static struct hwrng pasemi_rng = { - .name = MODULE_NAME, - .init = pasemi_rng_init, - .cleanup = pasemi_rng_cleanup, - .data_present = pasemi_rng_data_present, - .data_read = pasemi_rng_data_read, -}; - -static int __devinit rng_probe(struct of_device *ofdev, - const struct of_device_id *match) -{ - void __iomem *rng_regs; - struct device_node *rng_np = ofdev->node; - struct resource res; - int err = 0; - - err = of_address_to_resource(rng_np, 0, &res); - if (err) - return -ENODEV; - - rng_regs = ioremap(res.start, 0x100); - - if (!rng_regs) - return -ENOMEM; - - pasemi_rng.priv = (unsigned long)rng_regs; - - printk(KERN_INFO "Registering PA Semi RNG\n"); - - err = hwrng_register(&pasemi_rng); - - if (err) - iounmap(rng_regs); - - return err; -} - -static int __devexit rng_remove(struct of_device *dev) -{ - void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; - - hwrng_unregister(&pasemi_rng); - iounmap(rng_regs); - - return 0; -} - -static struct of_device_id rng_match[] = { - { - .compatible = "1682m-rng", - }, - {}, -}; - -static struct of_platform_driver rng_driver = { - .name = "pasemi-rng", - .match_table = rng_match, - .probe = rng_probe, - .remove = rng_remove, -}; - -static int __init rng_init(void) -{ - return of_register_platform_driver(&rng_driver); -} -module_init(rng_init); - -static void __exit rng_exit(void) -{ - of_unregister_platform_driver(&rng_driver); -} -module_exit(rng_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Egor Martovetsky "); -MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor"); diff --git a/trunk/drivers/char/ipmi/Kconfig b/trunk/drivers/char/ipmi/Kconfig index b894f67fdf14..a6dcb2918157 100644 --- a/trunk/drivers/char/ipmi/Kconfig +++ b/trunk/drivers/char/ipmi/Kconfig @@ -3,8 +3,6 @@ # menu "IPMI" - depends on HAS_IOMEM - config IPMI_HANDLER tristate 'IPMI top-level message handler' help diff --git a/trunk/drivers/char/mmtimer.c b/trunk/drivers/char/mmtimer.c index 6e55cfb9c65a..c09160383a53 100644 --- a/trunk/drivers/char/mmtimer.c +++ b/trunk/drivers/char/mmtimer.c @@ -705,13 +705,15 @@ static int __init mmtimer_init(void) maxn++; /* Allocate list of node ptrs to mmtimer_t's */ - timers = kzalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); + timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); if (timers == NULL) { printk(KERN_ERR "%s: failed to allocate memory for device\n", MMTIMER_NAME); goto out3; } + memset(timers,0,(sizeof(mmtimer_t *)*maxn)); + /* Allocate mmtimer_t's for each online node */ for_each_online_node(node) { timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c index b3d4ccc33a47..6ac3ca4c723c 100644 --- a/trunk/drivers/char/n_tty.c +++ b/trunk/drivers/char/n_tty.c @@ -1544,18 +1544,21 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol } struct tty_ldisc tty_ldisc_N_TTY = { - .magic = TTY_LDISC_MAGIC, - .name = "n_tty", - .open = n_tty_open, - .close = n_tty_close, - .flush_buffer = n_tty_flush_buffer, - .chars_in_buffer = n_tty_chars_in_buffer, - .read = read_chan, - .write = write_chan, - .ioctl = n_tty_ioctl, - .set_termios = n_tty_set_termios, - .poll = normal_poll, - .receive_buf = n_tty_receive_buf, - .write_wakeup = n_tty_write_wakeup + TTY_LDISC_MAGIC, /* magic */ + "n_tty", /* name */ + 0, /* num */ + 0, /* flags */ + n_tty_open, /* open */ + n_tty_close, /* close */ + n_tty_flush_buffer, /* flush_buffer */ + n_tty_chars_in_buffer, /* chars_in_buffer */ + read_chan, /* read */ + write_chan, /* write */ + n_tty_ioctl, /* ioctl */ + n_tty_set_termios, /* set_termios */ + normal_poll, /* poll */ + NULL, /* hangup */ + n_tty_receive_buf, /* receive_buf */ + n_tty_write_wakeup /* write_wakeup */ }; diff --git a/trunk/drivers/char/pcmcia/Kconfig b/trunk/drivers/char/pcmcia/Kconfig index f25facd97bb4..27c1179ee527 100644 --- a/trunk/drivers/char/pcmcia/Kconfig +++ b/trunk/drivers/char/pcmcia/Kconfig @@ -21,7 +21,6 @@ config SYNCLINK_CS config CARDMAN_4000 tristate "Omnikey Cardman 4000 support" depends on PCMCIA - select BITREVERSE help Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard reader. diff --git a/trunk/drivers/char/pcmcia/cm4000_cs.c b/trunk/drivers/char/pcmcia/cm4000_cs.c index fee58e03dbe2..e91b43a014b0 100644 --- a/trunk/drivers/char/pcmcia/cm4000_cs.c +++ b/trunk/drivers/char/pcmcia/cm4000_cs.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -195,17 +194,41 @@ static inline unsigned char xinb(unsigned short port) } #endif -static inline unsigned char invert_revert(unsigned char ch) -{ - return bitrev8(~ch); -} +#define b_0000 15 +#define b_0001 14 +#define b_0010 13 +#define b_0011 12 +#define b_0100 11 +#define b_0101 10 +#define b_0110 9 +#define b_0111 8 +#define b_1000 7 +#define b_1001 6 +#define b_1010 5 +#define b_1011 4 +#define b_1100 3 +#define b_1101 2 +#define b_1110 1 +#define b_1111 0 + +static unsigned char irtab[16] = { + b_0000, b_1000, b_0100, b_1100, + b_0010, b_1010, b_0110, b_1110, + b_0001, b_1001, b_0101, b_1101, + b_0011, b_1011, b_0111, b_1111 +}; static void str_invert_revert(unsigned char *b, int len) { int i; for (i = 0; i < len; i++) - b[i] = invert_revert(b[i]); + b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; +} + +static unsigned char invert_revert(unsigned char ch) +{ + return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; } #define ATRLENCK(dev,pos) \ @@ -1091,7 +1114,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, /* * wait for atr to become valid. * note: it is important to lock this code. if we dont, the monitor - * could be run between test_bit and the call to sleep on the + * could be run between test_bit and the the call the sleep on the * atr-queue. if *then* the monitor detects atr valid, it will wake up * any process on the atr-queue, *but* since we have been interrupted, * we do not yet sleep on this queue. this would result in a missed @@ -1858,11 +1881,8 @@ static int cm4000_probe(struct pcmcia_device *link) init_waitqueue_head(&dev->readq); ret = cm4000_config(link, i); - if (ret) { - dev_table[i] = NULL; - kfree(dev); + if (ret) return ret; - } class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); @@ -1887,7 +1907,7 @@ static void cm4000_detach(struct pcmcia_device *link) cm4000_release(link); dev_table[devno] = NULL; - kfree(dev); + kfree(dev); class_device_destroy(cmm_class, MKDEV(major, devno)); @@ -1936,14 +1956,12 @@ static int __init cmm_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - class_destroy(cmm_class); return major; } rc = pcmcia_register_driver(&cm4000_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); - class_destroy(cmm_class); return rc; } diff --git a/trunk/drivers/char/pcmcia/cm4040_cs.c b/trunk/drivers/char/pcmcia/cm4040_cs.c index af88181a17f4..f2e4ec4fd407 100644 --- a/trunk/drivers/char/pcmcia/cm4040_cs.c +++ b/trunk/drivers/char/pcmcia/cm4040_cs.c @@ -636,11 +636,8 @@ static int reader_probe(struct pcmcia_device *link) setup_timer(&dev->poll_timer, cm4040_do_poll, 0); ret = reader_config(link, i); - if (ret) { - dev_table[i] = NULL; - kfree(dev); + if (ret) return ret; - } class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i); @@ -711,14 +708,12 @@ static int __init cm4040_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - class_destroy(cmx_class); return major; } rc = pcmcia_register_driver(&reader_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); - class_destroy(cmx_class); return rc; } diff --git a/trunk/drivers/char/rio/riocmd.c b/trunk/drivers/char/rio/riocmd.c index 8cc60b693460..245f03195b7c 100644 --- a/trunk/drivers/char/rio/riocmd.c +++ b/trunk/drivers/char/rio/riocmd.c @@ -402,7 +402,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); - if (Rup < (unsigned short) MAX_RUP) { + if (Rup >= (unsigned short) MAX_RUP) { rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); } else rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); diff --git a/trunk/drivers/char/rocket.c b/trunk/drivers/char/rocket.c index a3fd7e7ba5a9..61a63da420c2 100644 --- a/trunk/drivers/char/rocket.c +++ b/trunk/drivers/char/rocket.c @@ -1014,6 +1014,9 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ + info->session = process_session(current); + info->pgrp = process_group(current); + if ((info->flags & ROCKET_INITIALIZED) == 0) { cp = &info->channel; sSetRxTrigger(cp, TRIG_1); diff --git a/trunk/drivers/char/rocket_int.h b/trunk/drivers/char/rocket_int.h index b4c53dfa7951..89b4d7b10d12 100644 --- a/trunk/drivers/char/rocket_int.h +++ b/trunk/drivers/char/rocket_int.h @@ -1158,6 +1158,8 @@ struct r_port { int xmit_head; int xmit_tail; int xmit_cnt; + int session; + int pgrp; int cd_status; int ignore_status_mask; int read_status_mask; diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c index 02b49bc00028..2a7736b5f2f7 100644 --- a/trunk/drivers/char/synclink_gt.c +++ b/trunk/drivers/char/synclink_gt.c @@ -1170,112 +1170,6 @@ static int ioctl(struct tty_struct *tty, struct file *file, return 0; } -/* - * support for 32 bit ioctl calls on 64 bit systems - */ -#ifdef CONFIG_COMPAT -static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params) -{ - struct MGSL_PARAMS32 tmp_params; - - DBGINFO(("%s get_params32\n", info->device_name)); - tmp_params.mode = (compat_ulong_t)info->params.mode; - tmp_params.loopback = info->params.loopback; - tmp_params.flags = info->params.flags; - tmp_params.encoding = info->params.encoding; - tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed; - tmp_params.addr_filter = info->params.addr_filter; - tmp_params.crc_type = info->params.crc_type; - tmp_params.preamble_length = info->params.preamble_length; - tmp_params.preamble = info->params.preamble; - tmp_params.data_rate = (compat_ulong_t)info->params.data_rate; - tmp_params.data_bits = info->params.data_bits; - tmp_params.stop_bits = info->params.stop_bits; - tmp_params.parity = info->params.parity; - if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32))) - return -EFAULT; - return 0; -} - -static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params) -{ - struct MGSL_PARAMS32 tmp_params; - - DBGINFO(("%s set_params32\n", info->device_name)); - if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32))) - return -EFAULT; - - spin_lock(&info->lock); - info->params.mode = tmp_params.mode; - info->params.loopback = tmp_params.loopback; - info->params.flags = tmp_params.flags; - info->params.encoding = tmp_params.encoding; - info->params.clock_speed = tmp_params.clock_speed; - info->params.addr_filter = tmp_params.addr_filter; - info->params.crc_type = tmp_params.crc_type; - info->params.preamble_length = tmp_params.preamble_length; - info->params.preamble = tmp_params.preamble; - info->params.data_rate = tmp_params.data_rate; - info->params.data_bits = tmp_params.data_bits; - info->params.stop_bits = tmp_params.stop_bits; - info->params.parity = tmp_params.parity; - spin_unlock(&info->lock); - - change_params(info); - - return 0; -} - -static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct slgt_info *info = tty->driver_data; - int rc = -ENOIOCTLCMD; - - if (sanity_check(info, tty->name, "compat_ioctl")) - return -ENODEV; - DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd)); - - switch (cmd) { - - case MGSL_IOCSPARAMS32: - rc = set_params32(info, compat_ptr(arg)); - break; - - case MGSL_IOCGPARAMS32: - rc = get_params32(info, compat_ptr(arg)); - break; - - case MGSL_IOCGPARAMS: - case MGSL_IOCSPARAMS: - case MGSL_IOCGTXIDLE: - case MGSL_IOCGSTATS: - case MGSL_IOCWAITEVENT: - case MGSL_IOCGIF: - case MGSL_IOCSGPIO: - case MGSL_IOCGGPIO: - case MGSL_IOCWAITGPIO: - case TIOCGICOUNT: - rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg))); - break; - - case MGSL_IOCSTXIDLE: - case MGSL_IOCTXENABLE: - case MGSL_IOCRXENABLE: - case MGSL_IOCTXABORT: - case TIOCMIWAIT: - case MGSL_IOCSIF: - rc = ioctl(tty, file, cmd, arg); - break; - } - - DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc)); - return rc; -} -#else -#define slgt_compat_ioctl NULL -#endif /* ifdef CONFIG_COMPAT */ - /* * proc fs support */ @@ -3552,7 +3446,6 @@ static const struct tty_operations ops = { .chars_in_buffer = chars_in_buffer, .flush_buffer = flush_buffer, .ioctl = ioctl, - .compat_ioctl = slgt_compat_ioctl, .throttle = throttle, .unthrottle = unthrottle, .send_xchar = send_xchar, diff --git a/trunk/drivers/char/tpm/Kconfig b/trunk/drivers/char/tpm/Kconfig index dc4e1ff7f56f..fe00c7dfb649 100644 --- a/trunk/drivers/char/tpm/Kconfig +++ b/trunk/drivers/char/tpm/Kconfig @@ -3,7 +3,6 @@ # menu "TPM devices" - depends on HAS_IOMEM config TCG_TPM tristate "TPM Hardware Support" @@ -34,7 +33,7 @@ config TCG_NSC tristate "National Semiconductor TPM Interface" depends on TCG_TPM && PNPACPI ---help--- - If you have a TPM security chip from National Semiconductor + If you have a TPM security chip from National Semicondutor say Yes and it will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_nsc. diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index fe62c2170d01..7710a6a77d97 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -151,12 +151,6 @@ static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_COMPAT -static long tty_compat_ioctl(struct file * file, unsigned int cmd, - unsigned long arg); -#else -#define tty_compat_ioctl NULL -#endif static int tty_fasync(int fd, struct file * filp, int on); static void release_tty(struct tty_struct *tty, int idx); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); @@ -939,6 +933,13 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (ld == NULL) return -EINVAL; + /* + * No more input please, we are switching. The new ldisc + * will update this value in the ldisc open function + */ + + tty->receive_room = 0; + /* * Problem: What do we do if this blocks ? */ @@ -950,13 +951,6 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) return 0; } - /* - * No more input please, we are switching. The new ldisc - * will update this value in the ldisc open function - */ - - tty->receive_room = 0; - o_ldisc = tty->ldisc; o_tty = tty->link; @@ -1149,8 +1143,8 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait) return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; } -static long hung_up_tty_ioctl(struct file * file, - unsigned int cmd, unsigned long arg) +static int hung_up_tty_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) { return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } @@ -1161,7 +1155,6 @@ static const struct file_operations tty_fops = { .write = tty_write, .poll = tty_poll, .ioctl = tty_ioctl, - .compat_ioctl = tty_compat_ioctl, .open = tty_open, .release = tty_release, .fasync = tty_fasync, @@ -1174,7 +1167,6 @@ static const struct file_operations ptmx_fops = { .write = tty_write, .poll = tty_poll, .ioctl = tty_ioctl, - .compat_ioctl = tty_compat_ioctl, .open = ptmx_open, .release = tty_release, .fasync = tty_fasync, @@ -1187,7 +1179,6 @@ static const struct file_operations console_fops = { .write = redirected_tty_write, .poll = tty_poll, .ioctl = tty_ioctl, - .compat_ioctl = tty_compat_ioctl, .open = tty_open, .release = tty_release, .fasync = tty_fasync, @@ -1198,8 +1189,7 @@ static const struct file_operations hung_up_tty_fops = { .read = hung_up_tty_read, .write = hung_up_tty_write, .poll = hung_up_tty_poll, - .unlocked_ioctl = hung_up_tty_ioctl, - .compat_ioctl = hung_up_tty_ioctl, + .ioctl = hung_up_tty_ioctl, .release = tty_release, }; @@ -1583,11 +1573,11 @@ void no_tty(void) /** - * stop_tty - propagate flow control + * stop_tty - propogate flow control * @tty: tty to stop * * Perform flow control to the driver. For PTY/TTY pairs we - * must also propagate the TIOCKPKT status. May be called + * must also propogate the TIOCKPKT status. May be called * on an already stopped device and will not re-call the driver * method. * @@ -1617,11 +1607,11 @@ void stop_tty(struct tty_struct *tty) EXPORT_SYMBOL(stop_tty); /** - * start_tty - propagate flow control + * 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 propagate the TIOCPKT status. If this + * 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. * @@ -3367,32 +3357,6 @@ int tty_ioctl(struct inode * inode, struct file * file, return retval; } -#ifdef CONFIG_COMPAT -static long tty_compat_ioctl(struct file * file, unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = file->f_dentry->d_inode; - struct tty_struct *tty = file->private_data; - struct tty_ldisc *ld; - int retval = -ENOIOCTLCMD; - - if (tty_paranoia_check(tty, inode, "tty_ioctl")) - return -EINVAL; - - if (tty->driver->compat_ioctl) { - retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg); - if (retval != -ENOIOCTLCMD) - return retval; - } - - ld = tty_ldisc_ref_wait(tty); - if (ld->compat_ioctl) - retval = ld->compat_ioctl(tty, file, cmd, arg); - tty_ldisc_deref(ld); - - return retval; -} -#endif /* * This implements the "Secure Attention Key" --- the idea is to @@ -3725,7 +3689,6 @@ void tty_set_operations(struct tty_driver *driver, driver->write_room = op->write_room; driver->chars_in_buffer = op->chars_in_buffer; driver->ioctl = op->ioctl; - driver->compat_ioctl = op->compat_ioctl; driver->set_termios = op->set_termios; driver->throttle = op->throttle; driver->unthrottle = op->unthrottle; diff --git a/trunk/drivers/char/watchdog/Kconfig b/trunk/drivers/char/watchdog/Kconfig index 1cad32c62ed3..60198a78974c 100644 --- a/trunk/drivers/char/watchdog/Kconfig +++ b/trunk/drivers/char/watchdog/Kconfig @@ -2,7 +2,9 @@ # Watchdog device configuration # -menuconfig WATCHDOG +menu "Watchdog Cards" + +config WATCHDOG bool "Watchdog Timer Support" ---help--- If you say Y here (and to one of the following options) and create a @@ -26,10 +28,9 @@ menuconfig WATCHDOG If unsure, say N. -if WATCHDOG - config WATCHDOG_NOWAYOUT bool "Disable watchdog shutdown on close" + depends on WATCHDOG help The default watchdog behaviour (which you get if you say N here) is to stop the timer if the process managing it closes the file @@ -42,11 +43,13 @@ config WATCHDOG_NOWAYOUT # comment "Watchdog Device Drivers" + depends on WATCHDOG # Architecture Independent config SOFT_WATCHDOG tristate "Software watchdog" + depends on WATCHDOG help A software monitoring watchdog. This will fail to reboot your system from some situations that the hardware watchdog will recover @@ -59,14 +62,14 @@ config SOFT_WATCHDOG config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" - depends on ARCH_AT91RM9200 + depends on WATCHDOG && ARCH_AT91RM9200 help Watchdog timer embedded into AT91RM9200 chips. This will reboot your system when the timeout is reached. config 21285_WATCHDOG tristate "DC21285 watchdog" - depends on FOOTBRIDGE + depends on WATCHDOG && FOOTBRIDGE help The Intel Footbridge chip contains a built-in watchdog circuit. Say Y here if you wish to use this. Alternatively say M to compile the @@ -80,7 +83,7 @@ config 21285_WATCHDOG config 977_WATCHDOG tristate "NetWinder WB83C977 watchdog" - depends on FOOTBRIDGE && ARCH_NETWINDER + depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER help Say Y here to include support for the WB977 watchdog included in NetWinder machines. Alternatively say M to compile the driver as @@ -90,7 +93,7 @@ config 977_WATCHDOG config IXP2000_WATCHDOG tristate "IXP2000 Watchdog" - depends on ARCH_IXP2000 + depends on WATCHDOG && ARCH_IXP2000 help Say Y here if to include support for the watchdog timer in the Intel IXP2000(2400, 2800, 2850) network processors. @@ -101,7 +104,7 @@ config IXP2000_WATCHDOG config IXP4XX_WATCHDOG tristate "IXP4xx Watchdog" - depends on ARCH_IXP4XX + depends on WATCHDOG && ARCH_IXP4XX help Say Y here if to include support for the watchdog timer in the Intel IXP4xx network processors. This driver can @@ -117,7 +120,7 @@ config IXP4XX_WATCHDOG config S3C2410_WATCHDOG tristate "S3C2410 Watchdog" - depends on ARCH_S3C2410 + depends on WATCHDOG && ARCH_S3C2410 help Watchdog timer block in the Samsung S3C2410 chips. This will reboot the system when the timer expires with the watchdog @@ -133,7 +136,7 @@ config S3C2410_WATCHDOG config SA1100_WATCHDOG tristate "SA1100/PXA2xx watchdog" - depends on ARCH_SA1100 || ARCH_PXA + depends on WATCHDOG && ( ARCH_SA1100 || ARCH_PXA ) help Watchdog timer embedded into SA11x0 and PXA2xx chips. This will reboot your system when timeout is reached. @@ -145,7 +148,7 @@ config SA1100_WATCHDOG config MPCORE_WATCHDOG tristate "MPcore watchdog" - depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS + depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS help Watchdog timer embedded into the MPcore system. @@ -154,7 +157,7 @@ config MPCORE_WATCHDOG config EP93XX_WATCHDOG tristate "EP93xx Watchdog" - depends on ARCH_EP93XX + depends on WATCHDOG && ARCH_EP93XX help Say Y here if to include support for the watchdog timer embedded in the Cirrus Logic EP93xx family of devices. @@ -164,14 +167,14 @@ config EP93XX_WATCHDOG config OMAP_WATCHDOG tristate "OMAP Watchdog" - depends on ARCH_OMAP16XX || ARCH_OMAP24XX + depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX) help Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog. Say 'Y' here to enable the OMAP1610/OMAP1710 watchdog timer. config PNX4008_WATCHDOG tristate "PNX4008 Watchdog" - depends on ARCH_PNX4008 + depends on WATCHDOG && ARCH_PNX4008 help Say Y here if to include support for the watchdog timer in the PNX4008 processor. @@ -184,7 +187,7 @@ config PNX4008_WATCHDOG config ACQUIRE_WDT tristate "Acquire SBC Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on Single Board Computers produced by Acquire Inc (and others). This watchdog @@ -198,7 +201,7 @@ config ACQUIRE_WDT config ADVANTECH_WDT tristate "Advantech SBC Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 help If you are configuring a Linux kernel for the Advantech single-board computer, say `Y' here to support its built-in watchdog timer @@ -207,7 +210,7 @@ config ADVANTECH_WDT config ALIM1535_WDT tristate "ALi M1535 PMU Watchdog Timer" - depends on X86 && PCI + depends on WATCHDOG && X86 && PCI ---help--- This is the driver for the hardware watchdog on the ALi M1535 PMU. @@ -218,7 +221,7 @@ config ALIM1535_WDT config ALIM7101_WDT tristate "ALi M7101 PMU Computer Watchdog" - depends on X86 && PCI + depends on WATCHDOG && X86 && PCI help This is the driver for the hardware watchdog on the ALi M7101 PMU as used in the x86 Cobalt servers. @@ -230,7 +233,7 @@ config ALIM7101_WDT config SC520_WDT tristate "AMD Elan SC520 processor Watchdog" - depends on X86 + depends on WATCHDOG && X86 help This is the driver for the hardware watchdog built in to the AMD "Elan" SC520 microcomputer commonly used in embedded systems. @@ -243,7 +246,7 @@ config SC520_WDT config EUROTECH_WDT tristate "Eurotech CPU-1220/1410 Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 help Enable support for the watchdog timer on the Eurotech CPU-1220 and CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product @@ -251,7 +254,7 @@ config EUROTECH_WDT config IB700_WDT tristate "IB700 SBC Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the IB700 Single Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog @@ -267,7 +270,7 @@ config IB700_WDT config IBMASR tristate "IBM Automatic Server Restart" - depends on X86 + depends on WATCHDOG && X86 help This is the driver for the IBM Automatic Server Restart watchdog timer built-in into some eServer xSeries machines. @@ -277,7 +280,7 @@ config IBMASR config WAFER_WDT tristate "ICP Wafer 5823 Single Board Computer Watchdog" - depends on X86 + depends on WATCHDOG && X86 help This is a driver for the hardware watchdog on the ICP Wafer 5823 Single Board Computer (and probably other similar models). @@ -287,7 +290,7 @@ config WAFER_WDT config I6300ESB_WDT tristate "Intel 6300ESB Timer/Watchdog" - depends on X86 && PCI + depends on WATCHDOG && X86 && PCI ---help--- Hardware driver for the watchdog timer built into the Intel 6300ESB controller hub. @@ -295,9 +298,31 @@ config I6300ESB_WDT To compile this driver as a module, choose M here: the module will be called i6300esb. +config I8XX_TCO + tristate "Intel i8xx TCO Timer/Watchdog" + depends on WATCHDOG && (X86 || IA64) && PCI + default n + ---help--- + Hardware driver for the TCO timer built into the Intel 82801 + I/O Controller Hub family. The TCO (Total Cost of Ownership) + timer is a watchdog timer that will reboot the machine after + its second expiration. The expiration time can be configured + with the "heartbeat" parameter. + + On some motherboards the driver may fail to reset the chipset's + NO_REBOOT flag which prevents the watchdog from rebooting the + machine. If this is the case you will get a kernel message like + "failed to reset NO_REBOOT flag, reboot disabled by hardware". + + To compile this driver as a module, choose M here: the + module will be called i8xx_tco. + + Note: This driver will be removed in the near future. Please + use the Intel TCO Timer/Watchdog driver. + config ITCO_WDT tristate "Intel TCO Timer/Watchdog" - depends on (X86 || IA64) && PCI + depends on WATCHDOG && (X86 || IA64) && PCI ---help--- Hardware driver for the intel TCO timer based watchdog devices. These drivers are included in the Intel 82801 I/O Controller @@ -326,7 +351,7 @@ config ITCO_VENDOR_SUPPORT config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" - depends on X86 + depends on WATCHDOG && X86 help This is a driver for National Semiconductor PC87307/PC97307 hardware watchdog cards as found on the SC1200. This watchdog is mainly used @@ -340,7 +365,7 @@ config SC1200_WDT config SCx200_WDT tristate "National Semiconductor SCx200 Watchdog" - depends on SCx200 && PCI + depends on WATCHDOG && SCx200 && PCI help Enable the built-in watchdog timer support on the National Semiconductor SCx200 processors. @@ -349,7 +374,7 @@ config SCx200_WDT config PC87413_WDT tristate "NS PC87413 watchdog" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the PC87413 chipset This watchdog simply watches your kernel to make sure it doesn't @@ -363,7 +388,7 @@ config PC87413_WDT config 60XX_WDT tristate "SBC-60XX Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 help This driver can be used with the watchdog timer found on some single board computers, namely the 6010 PII based computer. @@ -377,7 +402,7 @@ config 60XX_WDT config SBC8360_WDT tristate "SBC8360 Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the SBC8360 Single @@ -390,7 +415,7 @@ config SBC8360_WDT config CPU5_WDT tristate "SMA CPU5 Watchdog" - depends on X86 + depends on WATCHDOG && X86 ---help--- TBD. To compile this driver as a module, choose M here: the @@ -398,7 +423,7 @@ config CPU5_WDT config SMSC37B787_WDT tristate "Winbond SMsC37B787 Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog component on the Winbond SMsC37B787 chipset as used on the NetRunner Mainboard @@ -418,7 +443,7 @@ config SMSC37B787_WDT config W83627HF_WDT tristate "W83627HF Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83627HF chipset as used in Advantech PC-9578 and Tyan S2721-533 motherboards @@ -433,7 +458,7 @@ config W83627HF_WDT config W83697HF_WDT tristate "W83697HF/W83697HG Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83697HF/HG chipset as used in Dedibox/VIA motherboards (and likely others). @@ -448,7 +473,7 @@ config W83697HF_WDT config W83877F_WDT tristate "W83877F (EMACS) Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83877F chipset as used in EMACS PC-104 motherboards (and likely others). This @@ -463,7 +488,7 @@ config W83877F_WDT config W83977F_WDT tristate "W83977F (PCM-5335) Watchdog Timer" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83977F I/O chip as used in AAEON's PCM-5335 SBC (and likely others). This @@ -476,7 +501,7 @@ config W83977F_WDT config MACHZ_WDT tristate "ZF MachZ Watchdog" - depends on X86 + depends on WATCHDOG && X86 ---help--- If you are using a ZF Micro MachZ processor, say Y here, otherwise N. This is the driver for the watchdog timer built-in on that @@ -489,7 +514,7 @@ config MACHZ_WDT config SBC_EPX_C3_WATCHDOG tristate "Winsystems SBC EPX-C3 watchdog" - depends on X86 + depends on WATCHDOG && X86 ---help--- This is the driver for the built-in watchdog timer on the EPX-C3 Single-board computer made by Winsystems, Inc. @@ -512,19 +537,19 @@ config SBC_EPX_C3_WATCHDOG config 8xx_WDT tristate "MPC8xx Watchdog Timer" - depends on 8xx + depends on WATCHDOG && 8xx config 83xx_WDT tristate "MPC83xx Watchdog Timer" - depends on PPC_83xx + depends on WATCHDOG && PPC_83xx config MV64X60_WDT tristate "MV64X60 (Marvell Discovery) Watchdog Timer" - depends on MV64X60 + depends on WATCHDOG && MV64X60 config BOOKE_WDT bool "PowerPC Book-E Watchdog Timer" - depends on BOOKE || 4xx + depends on WATCHDOG && (BOOKE || 4xx) ---help--- Please see Documentation/watchdog/watchdog-api.txt for more information. @@ -533,7 +558,7 @@ config BOOKE_WDT config WATCHDOG_RTAS tristate "RTAS watchdog" - depends on PPC_RTAS + depends on WATCHDOG && PPC_RTAS help This driver adds watchdog support for the RTAS watchdog. @@ -544,23 +569,16 @@ config WATCHDOG_RTAS config INDYDOG tristate "Indy/I2 Hardware Watchdog" - depends on SGI_IP22 + depends on WATCHDOG && SGI_IP22 help Hardware driver 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. -config WDT_MTX1 - tristate "MTX-1 Hardware Watchdog" - depends on MIPS_MTX1 - help - Hardware driver for the MTX-1 boards. This is a watchdog timer that - will reboot the machine after a 100 seconds timer expired. - config WDT_RM9K_GPI tristate "RM9000/GPI hardware watchdog" - depends on CPU_RM9000 + depends on WATCHDOG && CPU_RM9000 help Watchdog implementation using the GPI hardware found on PMC-Sierra RM9xxx CPUs. @@ -572,7 +590,7 @@ config WDT_RM9K_GPI config ZVM_WATCHDOG tristate "z/VM Watchdog Timer" - depends on S390 + depends on WATCHDOG && S390 help IBM s/390 and zSeries machines running under z/VM 5.1 or later provide a virtual watchdog timer to their guest that cause a @@ -586,7 +604,7 @@ config ZVM_WATCHDOG config SH_WDT tristate "SuperH Watchdog" - depends on SUPERH + depends on WATCHDOG && SUPERH help This driver adds watchdog support for the integrated watchdog in the SuperH processors. If you have one of these processors and wish @@ -613,7 +631,7 @@ config SH_WDT_MMAP config WATCHDOG_CP1XXX tristate "CP1XXX Hardware Watchdog support" - depends on SPARC64 && PCI + depends on WATCHDOG && SPARC64 && PCI ---help--- This is the driver for the hardware watchdog timers present on Sun Microsystems CompactPCI models CP1400 and CP1500. @@ -627,7 +645,7 @@ config WATCHDOG_CP1XXX config WATCHDOG_RIO tristate "RIO Hardware Watchdog support" - depends on SPARC64 && PCI + depends on WATCHDOG && SPARC64 && PCI help Say Y here to support the hardware watchdog capability on Sun RIO machines. The watchdog timeout period is normally one minute but @@ -638,11 +656,11 @@ config WATCHDOG_RIO # comment "ISA-based Watchdog Cards" - depends on ISA + depends on WATCHDOG && ISA config PCWATCHDOG tristate "Berkshire Products ISA-PC Watchdog" - depends on ISA + depends on WATCHDOG && ISA ---help--- This is the driver for the Berkshire Products ISA-PC Watchdog card. This card simply watches your kernel to make sure it doesn't freeze, @@ -658,7 +676,7 @@ config PCWATCHDOG config MIXCOMWD tristate "Mixcom Watchdog" - depends on ISA + depends on WATCHDOG && ISA ---help--- This is a driver for the Mixcom hardware watchdog cards. This watchdog simply watches your kernel to make sure it doesn't freeze, @@ -672,7 +690,7 @@ config MIXCOMWD config WDT tristate "WDT Watchdog timer" - depends on ISA + depends on WATCHDOG && ISA ---help--- If you have a WDT500P or WDT501P watchdog board, say Y here, otherwise N. It is not possible to probe for this board, which means @@ -702,11 +720,11 @@ config WDT_501 # comment "PCI-based Watchdog Cards" - depends on PCI + depends on WATCHDOG && PCI config PCIPCWATCHDOG tristate "Berkshire Products PCI-PC Watchdog" - depends on PCI + depends on WATCHDOG && PCI ---help--- This is the driver for the Berkshire Products PCI-PC Watchdog card. This card simply watches your kernel to make sure it doesn't freeze, @@ -721,7 +739,7 @@ config PCIPCWATCHDOG config WDTPCI tristate "PCI-WDT500/501 Watchdog timer" - depends on PCI + depends on WATCHDOG && PCI ---help--- If you have a PCI-WDT500/501 watchdog board, say Y here, otherwise N. @@ -748,11 +766,11 @@ config WDT_501_PCI # comment "USB-based Watchdog Cards" - depends on USB + depends on WATCHDOG && USB config USBPCWATCHDOG tristate "Berkshire Products USB-PC Watchdog" - depends on USB + depends on WATCHDOG && USB ---help--- This is the driver for the Berkshire Products USB-PC Watchdog card. This card simply watches your kernel to make sure it doesn't freeze, @@ -765,4 +783,4 @@ config USBPCWATCHDOG Most people will say N. -endif # WATCHDOG +endmenu diff --git a/trunk/drivers/char/watchdog/Makefile b/trunk/drivers/char/watchdog/Makefile index 8bfc00cc7c2b..2cd8ff8d10ac 100644 --- a/trunk/drivers/char/watchdog/Makefile +++ b/trunk/drivers/char/watchdog/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o obj-$(CONFIG_IBMASR) += ibmasr.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o +obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o @@ -72,7 +73,6 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o # MIPS Architecture obj-$(CONFIG_INDYDOG) += indydog.o -obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o # S390 Architecture diff --git a/trunk/drivers/char/watchdog/cpu5wdt.c b/trunk/drivers/char/watchdog/cpu5wdt.c index d0d45a8b09f0..bcd7e36ca0aa 100644 --- a/trunk/drivers/char/watchdog/cpu5wdt.c +++ b/trunk/drivers/char/watchdog/cpu5wdt.c @@ -220,17 +220,17 @@ static int __devinit cpu5wdt_init(void) if ( verbose ) printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose); + if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) { + printk(KERN_ERR PFX "misc_register failed\n"); + goto no_misc; + } + if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { printk(KERN_ERR PFX "request_region failed\n"); err = -EBUSY; goto no_port; } - if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) { - printk(KERN_ERR PFX "misc_register failed\n"); - goto no_misc; - } - /* watchdog reboot? */ val = inb(port + CPU5WDT_STATUS_REG); val = (val >> 2) & 1; @@ -250,9 +250,9 @@ static int __devinit cpu5wdt_init(void) return 0; -no_misc: - release_region(port, CPU5WDT_EXTENT); no_port: + misc_deregister(&cpu5wdt_misc); +no_misc: return err; } diff --git a/trunk/drivers/char/watchdog/eurotechwdt.c b/trunk/drivers/char/watchdog/eurotechwdt.c index b070324e27a6..f70387f01b2b 100644 --- a/trunk/drivers/char/watchdog/eurotechwdt.c +++ b/trunk/drivers/char/watchdog/eurotechwdt.c @@ -413,10 +413,17 @@ static int __init eurwdt_init(void) { int ret; + ret = misc_register(&eurwdt_miscdev); + if (ret) { + printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", + WATCHDOG_MINOR); + goto out; + } + ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); if(ret) { printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); - goto out; + goto outmisc; } if (!request_region(io, 2, "eurwdt")) { @@ -431,13 +438,6 @@ static int __init eurwdt_init(void) goto outreg; } - ret = misc_register(&eurwdt_miscdev); - if (ret) { - printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto outreboot; - } - eurwdt_unlock_chip(); ret = 0; @@ -448,14 +448,14 @@ static int __init eurwdt_init(void) out: return ret; -outreboot: - unregister_reboot_notifier(&eurwdt_notifier); - outreg: release_region(io, 2); outirq: free_irq(irq, NULL); + +outmisc: + misc_deregister(&eurwdt_miscdev); goto out; } diff --git a/trunk/drivers/char/watchdog/i8xx_tco.c b/trunk/drivers/char/watchdog/i8xx_tco.c new file mode 100644 index 000000000000..a62ef48a15ae --- /dev/null +++ b/trunk/drivers/char/watchdog/i8xx_tco.c @@ -0,0 +1,571 @@ +/* + * i8xx_tco: TCO timer driver for i8xx chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the following I/O controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * 82801AA (ICH) : document number 290655-003, 290677-014, + * 82801AB (ICHO) : document number 290655-003, 290677-014, + * 82801BA (ICH2) : document number 290687-002, 298242-027, + * 82801BAM (ICH2-M) : document number 290687-002, 298242-027, + * 82801CA (ICH3-S) : document number 290733-003, 290739-013, + * 82801CAM (ICH3-M) : document number 290716-001, 290718-007, + * 82801DB (ICH4) : document number 290744-001, 290745-020, + * 82801DBM (ICH4-M) : document number 252337-001, 252663-005, + * 82801E (C-ICH) : document number 273599-001, 273645-002, + * 82801EB (ICH5) : document number 252516-001, 252517-003, + * 82801ER (ICH5R) : document number 252516-001, 252517-003, + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + * 20011214 Matt Domsch + * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Didn't add timeout option as i810_margin already exists. + * 20020224 Joel Becker, Wim Van Sebroeck + * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, + * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. + * 20020412 Rob Radez , Wim Van Sebroeck + * 0.05 Fix possible timer_alive race, add expect close support, + * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and + * WDIOC_SETOPTIONS), made i810tco_getdevice __init, + * removed boot_status, removed tco_timer_read, + * added support for 82801DB and 82801E chipset, + * added support for 82801EB and 8280ER chipset, + * general cleanup. + * 20030921 Wim Van Sebroeck + * 0.06 change i810_margin to heartbeat, use module_param, + * added notify system support, renamed module to i8xx_tco. + * 20050128 Wim Van Sebroeck + * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW + * chipsets. Also added support for the "undocumented" ICH7 chipset. + * 20050807 Wim Van Sebroeck + * 0.08 Make sure that the watchdog is only "armed" when started. + * (Kernel Bug 4251) + * 20060416 Wim Van Sebroeck + * 0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and + * ICH7 chipsets. (See Kernel Bug 6031 - other code will support these + * chipsets) + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "i8xx_tco.h" + +/* Module and version information */ +#define TCO_VERSION "0.09" +#define TCO_MODULE_NAME "i8xx TCO timer" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION +#define PFX TCO_MODULE_NAME ": " + +/* internal variables */ +static unsigned int ACPIBASE; +static spinlock_t tco_lock; /* Guards the hardware */ +static unsigned long timer_alive; +static char tco_expect_close; +static struct pci_dev *i8xx_tco_pci; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2 0 = The TCO timer is enabled to count */ + val = inb (TCO1_CNT + 1); + val &= 0xf7; + outb (val, TCO1_CNT + 1); + val = inb (TCO1_CNT + 1); + + spin_unlock(&tco_lock); + + if (val & 0x08) + return -1; + return 0; +} + +static int tco_timer_stop (void) +{ + unsigned char val, val1; + + spin_lock(&tco_lock); + /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ + val = inb (TCO1_CNT + 1); + val |= 0x08; + outb (val, TCO1_CNT + 1); + val = inb (TCO1_CNT + 1); + + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + + spin_unlock(&tco_lock); + + if ((val & 0x08) == 0) + return -1; + return 0; +} + +static int tco_timer_keepalive (void) +{ + spin_lock(&tco_lock); + /* Reload the timer by writing to the TCO Timer Reload register */ + outb (0x01, TCO1_RLD); + spin_unlock(&tco_lock); + return 0; +} + +static int tco_timer_set_heartbeat (int t) +{ + unsigned char val; + unsigned char tmrval; + + tmrval = seconds_to_ticks(t); + /* from the specs: */ + /* "Values of 0h-3h are ignored and should not be attempted" */ + if (tmrval > 0x3f || tmrval < 0x04) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + spin_lock(&tco_lock); + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + spin_unlock(&tco_lock); + + if ((val & 0x3f) != tmrval) + return -EINVAL; + + heartbeat = t; + return 0; +} + +static int tco_timer_get_timeleft (int *time_left) +{ + unsigned char val; + + spin_lock(&tco_lock); + + /* read the TCO Timer */ + val = inb (TCO1_RLD); + val &= 0x3f; + + spin_unlock(&tco_lock); + + *time_left = (int)((val * 6) / 10); + + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int i8xx_tco_open (struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_keepalive (); + tco_timer_start (); + return nonseekable_open(inode, file); +} + +static int i8xx_tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (tco_expect_close == 42) { + tco_timer_stop (); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + tco_timer_keepalive (); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t i8xx_tco_write (struct file *file, const char __user *data, + size_t len, loff_t * ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + tco_expect_close = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_keepalive (); + } + return len; +} + +static int i8xx_tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_heartbeat; + int time_left; + void __user *argp = (void __user *)arg; + int __user *p = argp; + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = TCO_MODULE_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user (0, p); + + case WDIOC_KEEPALIVE: + tco_timer_keepalive (); + return 0; + + case WDIOC_SETOPTIONS: + { + if (get_user (new_options, p)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + tco_timer_stop (); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + tco_timer_keepalive (); + tco_timer_start (); + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + if (get_user(new_heartbeat, p)) + return -EFAULT; + + if (tco_timer_set_heartbeat(new_heartbeat)) + return -EINVAL; + + tco_timer_keepalive (); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, p); + + case WDIOC_GETTIMELEFT: + { + if (tco_timer_get_timeleft(&time_left)) + return -EINVAL; + + return put_user(time_left, p); + } + + default: + return -ENOTTY; + } +} + +/* + * Notify system + */ + +static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + tco_timer_stop (); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static const struct file_operations i8xx_tco_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = i8xx_tco_write, + .ioctl = i8xx_tco_ioctl, + .open = i8xx_tco_open, + .release = i8xx_tco_release, +}; + +static struct miscdevice i8xx_tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &i8xx_tco_fops, +}; + +static struct notifier_block i8xx_tco_notifier = { + .notifier_call = i8xx_tco_notify_sys, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id i8xx_tco_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1) }, + { }, /* End of list */ +}; +MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); + +/* + * Init & exit routines + */ + +static unsigned char __init i8xx_tco_getdevice (void) +{ + struct pci_dev *dev = NULL; + u8 val1, val2; + u16 badr; + /* + * Find the PCI device + */ + + for_each_pci_dev(dev) + if (pci_match_id(i8xx_tco_pci_tbl, dev)) { + i8xx_tco_pci = dev; + break; + } + + if (i8xx_tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i8xx_tco_pci, 0x40, &val1); + pci_read_config_byte (i8xx_tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR PFX "failed to get TCOBASE address\n"); + pci_dev_put(i8xx_tco_pci); + return 0; + } + + /* Check chipset's NO_REBOOT bit */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); + pci_dev_put(i8xx_tco_pci); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Disable reboots untill the watchdog starts */ + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + + /* Set the TCO_EN bit in SMI_EN register */ + if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + SMI_EN + 1); + pci_dev_put(i8xx_tco_pci); + return 0; + } + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + release_region (SMI_EN + 1, 1); + return 1; + } + return 0; +} + +static int __init watchdog_init (void) +{ + int ret; + + spin_lock_init(&tco_lock); + + /* Check whether or not the hardware watchdog is there */ + if (!i8xx_tco_getdevice () || i8xx_tco_pci == NULL) + return -ENODEV; + + if (!request_region (TCOBASE, 0x10, "i8xx TCO")) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + TCOBASE); + ret = -EIO; + goto out; + } + + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + outb (3, TCO2_STS); + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (tco_timer_set_heartbeat (heartbeat)) { + heartbeat = WATCHDOG_HEARTBEAT; + tco_timer_set_heartbeat (heartbeat); + printk(KERN_INFO PFX "heartbeat value must be 2, All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * For history and the complete list of supported I/O Controller Hub's + * see i8xx_tco.c + */ + + +/* + * Some address definitions for the TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff --git a/trunk/drivers/char/watchdog/ibmasr.c b/trunk/drivers/char/watchdog/ibmasr.c index 94155f6136c2..8195f5023d85 100644 --- a/trunk/drivers/char/watchdog/ibmasr.c +++ b/trunk/drivers/char/watchdog/ibmasr.c @@ -367,17 +367,18 @@ static int __init ibmasr_init(void) if (!asr_type) return -ENODEV; - rc = asr_get_base_address(); - if (rc) - return rc; - rc = misc_register(&asr_miscdev); if (rc < 0) { - release_region(asr_base, asr_length); printk(KERN_ERR PFX "failed to register misc device\n"); return rc; } + rc = asr_get_base_address(); + if (rc) { + misc_deregister(&asr_miscdev); + return rc; + } + return 0; } diff --git a/trunk/drivers/char/watchdog/machzwd.c b/trunk/drivers/char/watchdog/machzwd.c index a0d27160c80e..76c7fa37fa6c 100644 --- a/trunk/drivers/char/watchdog/machzwd.c +++ b/trunk/drivers/char/watchdog/machzwd.c @@ -440,6 +440,13 @@ static int __init zf_init(void) spin_lock_init(&zf_lock); spin_lock_init(&zf_port_lock); + ret = misc_register(&zf_miscdev); + if (ret){ + printk(KERN_ERR "can't misc_register on minor=%d\n", + WATCHDOG_MINOR); + goto out; + } + if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ printk(KERN_ERR "cannot reserve I/O ports at %d\n", ZF_IOBASE); @@ -454,23 +461,16 @@ static int __init zf_init(void) goto no_reboot; } - ret = misc_register(&zf_miscdev); - if (ret){ - printk(KERN_ERR "can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto no_misc; - } - zf_set_status(0); zf_set_control(0); return 0; -no_misc: - unregister_reboot_notifier(&zf_notifier); no_reboot: release_region(ZF_IOBASE, 3); no_region: + misc_deregister(&zf_miscdev); +out: return ret; } diff --git a/trunk/drivers/char/watchdog/mtx-1_wdt.c b/trunk/drivers/char/watchdog/mtx-1_wdt.c deleted file mode 100644 index 419ab445c944..000000000000 --- a/trunk/drivers/char/watchdog/mtx-1_wdt.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Driver for the MTX-1 Watchdog. - * - * (C) Copyright 2005 4G Systems , All Rights Reserved. - * http://www.4g-systems.biz - * - * (C) Copyright 2007 OpenWrt.org, Florian Fainelli - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Michael Stickel nor 4G Systems admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2005 4G Systems - * - * Release 0.01. - * Author: Michael Stickel michael.stickel@4g-systems.biz - * - * Release 0.02. - * Author: Florian Fainelli florian@openwrt.org - * use the Linux watchdog/timer APIs - * - * The Watchdog is configured to reset the MTX-1 - * if it is not triggered for 100 seconds. - * It should not be triggered more often than 1.6 seconds. - * - * A timer triggers the watchdog every 5 seconds, until - * it is opened for the first time. After the first open - * it MUST be triggered every 2..95 seconds. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MTX1_WDT_INTERVAL (5 * HZ) - -static int ticks = 100 * HZ; - -static struct { - struct completion stop; - volatile int running; - struct timer_list timer; - volatile int queue; - int default_ticks; - unsigned long inuse; -} mtx1_wdt_device; - -static void mtx1_wdt_trigger(unsigned long unused) -{ - u32 tmp; - - if (mtx1_wdt_device.running) - ticks--; - /* - * toggle GPIO2_15 - */ - tmp = au_readl(GPIO2_DIR); - tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15)); - au_writel (tmp, GPIO2_DIR); - - if (mtx1_wdt_device.queue && ticks) - mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); - else { - complete(&mtx1_wdt_device.stop); - } -} - -static void mtx1_wdt_reset(void) -{ - ticks = mtx1_wdt_device.default_ticks; -} - - -static void mtx1_wdt_start(void) -{ - if (!mtx1_wdt_device.queue) { - mtx1_wdt_device.queue = 1; - au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR); - mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); - } - mtx1_wdt_device.running++; -} - -static int mtx1_wdt_stop(void) -{ - if (mtx1_wdt_device.queue) { - mtx1_wdt_device.queue = 0; - au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR); - } - - ticks = mtx1_wdt_device.default_ticks; - - return 0; -} - -/* Filesystem functions */ - -static int mtx1_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &mtx1_wdt_device.inuse)) - return -EBUSY; - - return nonseekable_open(inode, file); -} - - -static int mtx1_wdt_release(struct inode *inode, struct file *file) -{ - clear_bit(0, &mtx1_wdt_device.inuse); - return 0; -} - -static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - unsigned int value; - static struct watchdog_info ident = - { - .options = WDIOF_CARDRESET, - .identity = "MTX-1 WDT", - }; - - switch(cmd) { - case WDIOC_KEEPALIVE: - mtx1_wdt_reset(); - break; - case WDIOC_GETSTATUS: - if ( copy_to_user(argp, &value, sizeof(int)) ) - return -EFAULT; - break; - case WDIOC_GETSUPPORT: - if ( copy_to_user(argp, &ident, sizeof(ident)) ) - return -EFAULT; - break; - case WDIOC_SETOPTIONS: - if ( copy_from_user(&value, argp, sizeof(int)) ) - return -EFAULT; - switch(value) { - case WDIOS_ENABLECARD: - mtx1_wdt_start(); - break; - case WDIOS_DISABLECARD: - return mtx1_wdt_stop(); - default: - return -EINVAL; - } - break; - default: - return -ENOTTY; - } - return 0; -} - - -static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - if (!count) - return -EIO; - - mtx1_wdt_reset(); - return count; -} - -static struct file_operations mtx1_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = mtx1_wdt_ioctl, - .open = mtx1_wdt_open, - .write = mtx1_wdt_write, - .release = mtx1_wdt_release -}; - - -static struct miscdevice mtx1_wdt_misc = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mtx1_wdt_fops -}; - - -static int __init mtx1_wdt_init(void) -{ - int ret; - - if ((ret = misc_register(&mtx1_wdt_misc)) < 0) { - printk(KERN_ERR " mtx-1_wdt : failed to register\n"); - return ret; - } - - init_completion(&mtx1_wdt_device.stop); - mtx1_wdt_device.queue = 0; - - clear_bit(0, &mtx1_wdt_device.inuse); - - setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L); - - mtx1_wdt_device.default_ticks = ticks; - - mtx1_wdt_start(); - - printk(KERN_INFO "MTX-1 Watchdog driver\n"); - - return 0; -} - -static void __exit mtx1_wdt_exit(void) -{ - if (mtx1_wdt_device.queue) { - mtx1_wdt_device.queue = 0; - wait_for_completion(&mtx1_wdt_device.stop); - } - misc_deregister(&mtx1_wdt_misc); -} - -module_init(mtx1_wdt_init); -module_exit(mtx1_wdt_exit); - -MODULE_AUTHOR("Michael Stickel, Florian Fainelli"); -MODULE_DESCRIPTION("Driver for the MTX-1 watchdog"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/char/watchdog/pcwd.c b/trunk/drivers/char/watchdog/pcwd.c index 7b41434fac8c..6e8b5705b5b7 100644 --- a/trunk/drivers/char/watchdog/pcwd.c +++ b/trunk/drivers/char/watchdog/pcwd.c @@ -59,10 +59,10 @@ #include /* For jiffies stuff */ #include /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ #include /* For the watchdog specific items */ -#include /* For kernel_power_off() */ +#include /* For notifier support */ +#include /* For reboot_notifier stuff */ #include /* For __init/__exit/... */ #include /* For file operations */ -#include /* For isa devices */ #include /* For io-port access */ #include /* For spin_lock/spin_unlock/... */ @@ -70,8 +70,8 @@ #include /* For inb/outb/... */ /* Module and version information */ -#define WATCHDOG_VERSION "1.20" -#define WATCHDOG_DATE "18 Feb 2007" +#define WATCHDOG_VERSION "1.18" +#define WATCHDOG_DATE "21 Jan 2007" #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" #define WATCHDOG_NAME "pcwd" #define PFX WATCHDOG_NAME ": " @@ -88,15 +88,6 @@ #define PCWD_REVISION_A 1 #define PCWD_REVISION_C 2 -/* - * These are the auto-probe addresses available. - * - * Revision A only uses ports 0x270 and 0x370. Revision C introduced 0x350. - * Revision A has an address range of 2 addresses, while Revision C has 4. - */ -#define PCWD_ISA_NR_CARDS 3 -static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; - /* * These are the defines that describe the control status bits for the * PCI-PC Watchdog card. @@ -494,7 +485,7 @@ static int pcwd_get_status(int *status) if (control_status & WD_T110) { *status |= WDIOF_OVERHEAT; if (temp_panic) { - printk(KERN_INFO PFX "Temperature overheat trip!\n"); + printk (KERN_INFO PFX "Temperature overheat trip!\n"); kernel_power_off(); /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ } @@ -506,7 +497,7 @@ static int pcwd_get_status(int *status) if (control_status & WD_REVC_TTRP) { *status |= WDIOF_OVERHEAT; if (temp_panic) { - printk(KERN_INFO PFX "Temperature overheat trip!\n"); + printk (KERN_INFO PFX "Temperature overheat trip!\n"); kernel_power_off(); /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ } @@ -742,6 +733,20 @@ static int pcwd_temp_close(struct inode *inode, struct file *file) return 0; } +/* + * Notify system + */ + +static int pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + pcwd_stop(); + } + + return NOTIFY_DONE; +} + /* * Kernel Interfaces */ @@ -775,6 +780,10 @@ static struct miscdevice temp_miscdev = { .fops = &pcwd_temp_fops, }; +static struct notifier_block pcwd_notifier = { + .notifier_call = pcwd_notify_sys, +}; + /* * Init & exit routines */ @@ -794,67 +803,10 @@ static inline int get_revision(void) return r; } -/* - * The ISA cards have a heartbeat bit in one of the registers, which - * register is card dependent. The heartbeat bit is monitored, and if - * found, is considered proof that a Berkshire card has been found. - * The initial rate is once per second at board start up, then twice - * per second for normal operation. - */ -static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) -{ - int base_addr=pcwd_ioports[id]; - int port0, last_port0; /* Reg 0, in case it's REV A */ - int port1, last_port1; /* Register 1 for REV C cards */ - int i; - int retval; - - if (debug >= DEBUG) - printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n", - id); - - if (!request_region (base_addr, 4, "PCWD")) { - printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr); - return 0; - } - - retval = 0; - - port0 = inb_p(base_addr); /* For REV A boards */ - port1 = inb_p(base_addr + 1); /* For REV C boards */ - if (port0 != 0xff || port1 != 0xff) { - /* Not an 'ff' from a floating bus, so must be a card! */ - for (i = 0; i < 4; ++i) { - - msleep(500); - - last_port0 = port0; - last_port1 = port1; - - port0 = inb_p(base_addr); - port1 = inb_p(base_addr + 1); - - /* Has either hearbeat bit changed? */ - if ((port0 ^ last_port0) & WD_HRTBT || - (port1 ^ last_port1) & WD_REVC_HRBT) { - retval = 1; - break; - } - } - } - release_region (base_addr, 4); - - return retval; -} - -static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) +static int __devinit pcwatchdog_init(int base_addr) { int ret; - if (debug >= DEBUG) - printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n", - id); - cards_found++; if (cards_found == 1) printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); @@ -864,13 +816,11 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) return -ENODEV; } - if (pcwd_ioports[id] == 0x0000) { + if (base_addr == 0x0000) { printk(KERN_ERR PFX "No I/O-Address for card detected\n"); return -ENODEV; } - pcwd_private.io_addr = pcwd_ioports[id]; - - spin_lock_init(&pcwd_private.io_lock); + pcwd_private.io_addr = base_addr; /* Check card's revision */ pcwd_private.revision = get_revision(); @@ -878,8 +828,8 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", pcwd_private.io_addr); - ret=-EIO; - goto error_request_region; + pcwd_private.io_addr = 0x0000; + return -EIO; } /* Initial variables */ @@ -915,12 +865,24 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) WATCHDOG_HEARTBEAT); } + ret = register_reboot_notifier(&pcwd_notifier); + if (ret) { + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; + return ret; + } + if (pcwd_private.supports_temp) { ret = misc_register(&temp_miscdev); if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", TEMP_MINOR, ret); - goto error_misc_register_temp; + unregister_reboot_notifier(&pcwd_notifier); + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; + return ret; } } @@ -928,34 +890,22 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); - goto error_misc_register_watchdog; + if (pcwd_private.supports_temp) + misc_deregister(&temp_miscdev); + unregister_reboot_notifier(&pcwd_notifier); + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; + return ret; } printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", heartbeat, nowayout); return 0; - -error_misc_register_watchdog: - if (pcwd_private.supports_temp) - misc_deregister(&temp_miscdev); -error_misc_register_temp: - release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); -error_request_region: - pcwd_private.io_addr = 0x0000; - cards_found--; - return ret; } -static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id) +static void __devexit pcwatchdog_exit(void) { - if (debug >= DEBUG) - printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n", - id); - - if (!pcwd_private.io_addr) - return 1; - /* Disable the board */ if (!nowayout) pcwd_stop(); @@ -964,50 +914,102 @@ static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id) misc_deregister(&pcwd_miscdev); if (pcwd_private.supports_temp) misc_deregister(&temp_miscdev); + unregister_reboot_notifier(&pcwd_notifier); release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); pcwd_private.io_addr = 0x0000; cards_found--; - - return 0; } -static void pcwd_isa_shutdown(struct device *dev, unsigned int id) +/* + * The ISA cards have a heartbeat bit in one of the registers, which + * register is card dependent. The heartbeat bit is monitored, and if + * found, is considered proof that a Berkshire card has been found. + * The initial rate is once per second at board start up, then twice + * per second for normal operation. + */ +static int __init pcwd_checkcard(int base_addr) { - if (debug >= DEBUG) - printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n", - id); + int port0, last_port0; /* Reg 0, in case it's REV A */ + int port1, last_port1; /* Register 1 for REV C cards */ + int i; + int retval; - pcwd_stop(); + if (!request_region (base_addr, 4, "PCWD")) { + printk (KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr); + return 0; + } + + retval = 0; + + port0 = inb_p(base_addr); /* For REV A boards */ + port1 = inb_p(base_addr + 1); /* For REV C boards */ + if (port0 != 0xff || port1 != 0xff) { + /* Not an 'ff' from a floating bus, so must be a card! */ + for (i = 0; i < 4; ++i) { + + msleep(500); + + last_port0 = port0; + last_port1 = port1; + + port0 = inb_p(base_addr); + port1 = inb_p(base_addr + 1); + + /* Has either hearbeat bit changed? */ + if ((port0 ^ last_port0) & WD_HRTBT || + (port1 ^ last_port1) & WD_REVC_HRBT) { + retval = 1; + break; + } + } + } + release_region (base_addr, 4); + + return retval; } -static struct isa_driver pcwd_isa_driver = { - .match = pcwd_isa_match, - .probe = pcwd_isa_probe, - .remove = __devexit_p(pcwd_isa_remove), - .shutdown = pcwd_isa_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = WATCHDOG_NAME, - }, -}; +/* + * These are the auto-probe addresses available. + * + * Revision A only uses ports 0x270 and 0x370. Revision C introduced 0x350. + * Revision A has an address range of 2 addresses, while Revision C has 4. + */ +static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; static int __init pcwd_init_module(void) { - return isa_register_driver(&pcwd_isa_driver, PCWD_ISA_NR_CARDS); + int i, found = 0; + + spin_lock_init(&pcwd_private.io_lock); + + for (i = 0; pcwd_ioports[i] != 0; i++) { + if (pcwd_checkcard(pcwd_ioports[i])) { + if (!(pcwatchdog_init(pcwd_ioports[i]))) + found++; + } + } + + if (!found) { + printk (KERN_INFO PFX "No card detected, or port not available\n"); + return -ENODEV; + } + + return 0; } static void __exit pcwd_cleanup_module(void) { - isa_unregister_driver(&pcwd_isa_driver); + if (pcwd_private.io_addr) + pcwatchdog_exit(); + printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); } module_init(pcwd_init_module); module_exit(pcwd_cleanup_module); -MODULE_AUTHOR("Ken Hollis , Wim Van Sebroeck "); +MODULE_AUTHOR("Ken Hollis "); MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver"); -MODULE_VERSION(WATCHDOG_VERSION); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff --git a/trunk/drivers/char/watchdog/pcwd_usb.c b/trunk/drivers/char/watchdog/pcwd_usb.c index 1e7a6719d5ba..31037f9c9ffe 100644 --- a/trunk/drivers/char/watchdog/pcwd_usb.c +++ b/trunk/drivers/char/watchdog/pcwd_usb.c @@ -146,7 +146,7 @@ struct usb_pcwd_private { atomic_t cmd_received; /* true if we received a report after a command */ int exists; /* Wether or not the device exists */ - struct mutex mtx; /* locks this structure */ + struct semaphore sem; /* locks this structure */ }; static struct usb_pcwd_private *usb_pcwd_device; @@ -635,7 +635,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi usb_pcwd_device = usb_pcwd; - mutex_init(&usb_pcwd->mtx); + init_MUTEX (&usb_pcwd->sem); usb_pcwd->udev = udev; usb_pcwd->interface = interface; usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; @@ -763,7 +763,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) usb_pcwd = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); - mutex_lock(&usb_pcwd->mtx); + down (&usb_pcwd->sem); /* Stop the timer before we leave */ if (!nowayout) @@ -777,7 +777,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) misc_deregister(&usb_pcwd_temperature_miscdev); unregister_reboot_notifier(&usb_pcwd_notifier); - mutex_unlock(&usb_pcwd->mtx); + up (&usb_pcwd->sem); /* Delete the USB PCWD device */ usb_pcwd_delete(usb_pcwd); diff --git a/trunk/drivers/char/watchdog/s3c2410_wdt.c b/trunk/drivers/char/watchdog/s3c2410_wdt.c index 20fa29ca7404..dff6cb5dc9a7 100644 --- a/trunk/drivers/char/watchdog/s3c2410_wdt.c +++ b/trunk/drivers/char/watchdog/s3c2410_wdt.c @@ -379,14 +379,14 @@ static int s3c2410wdt_probe(struct platform_device *pdev) DBG("probe: mapped wdt_base=%p\n", wdt_base); - wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (wdt_irq == NULL) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { printk(KERN_INFO PFX "failed to get irq resource\n"); ret = -ENOENT; goto err_map; } - ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev); + ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev); if (ret != 0) { printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); goto err_map; diff --git a/trunk/drivers/char/watchdog/sbc8360.c b/trunk/drivers/char/watchdog/sbc8360.c index 285d85289532..67ae42685e75 100644 --- a/trunk/drivers/char/watchdog/sbc8360.c +++ b/trunk/drivers/char/watchdog/sbc8360.c @@ -333,17 +333,18 @@ static int __init sbc8360_init(void) int res; unsigned long int mseconds = 60000; - if (timeout < 0 || timeout > 63) { - printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n"); - res = -EINVAL; - goto out; + spin_lock_init(&sbc8360_lock); + res = misc_register(&sbc8360_miscdev); + if (res) { + printk(KERN_ERR PFX "failed to register misc device\n"); + goto out_nomisc; } if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) { printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n", SBC8360_ENABLE); res = -EIO; - goto out; + goto out_noenablereg; } if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) { printk(KERN_ERR PFX @@ -359,11 +360,10 @@ static int __init sbc8360_init(void) goto out_noreboot; } - spin_lock_init(&sbc8360_lock); - res = misc_register(&sbc8360_miscdev); - if (res) { - printk(KERN_ERR PFX "failed to register misc device\n"); - goto out_nomisc; + if (timeout < 0 || timeout > 63) { + printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n"); + res = -EINVAL; + goto out_noreboot; } wd_margin = wd_times[timeout][0]; @@ -383,13 +383,13 @@ static int __init sbc8360_init(void) return 0; - out_nomisc: - unregister_reboot_notifier(&sbc8360_notifier); out_noreboot: + release_region(SBC8360_ENABLE, 1); release_region(SBC8360_BASETIME, 1); + out_noenablereg: out_nobasetimereg: - release_region(SBC8360_ENABLE, 1); - out: + misc_deregister(&sbc8360_miscdev); + out_nomisc: return res; } diff --git a/trunk/drivers/char/watchdog/w83627hf_wdt.c b/trunk/drivers/char/watchdog/w83627hf_wdt.c index b46e7f47d705..337ee42c90dd 100644 --- a/trunk/drivers/char/watchdog/w83627hf_wdt.c +++ b/trunk/drivers/char/watchdog/w83627hf_wdt.c @@ -1,8 +1,5 @@ /* - * w83627hf/thf WDT driver - * - * (c) Copyright 2007 Vlad Drukker - * added support for W83627THF. + * w83627hf WDT driver * * (c) Copyright 2003 Pádraig Brady * @@ -42,7 +39,7 @@ #include #include -#define WATCHDOG_NAME "w83627hf/thf WDT" +#define WATCHDOG_NAME "w83627hf WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ @@ -53,7 +50,7 @@ static spinlock_t io_lock; /* You must set this - there is no sane way to probe for this board. */ static int wdt_io = 0x2E; module_param(wdt_io, int, 0); -MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)"); +MODULE_PARM_DESC(wdt_io, "w83627hf WDT io port (default 0x2E)"); static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); @@ -74,19 +71,9 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _ static void w83627hf_select_wd_register(void) { - unsigned char c; outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Again according to manual */ - outb(0x20, WDT_EFER); /* check chip version */ - c = inb(WDT_EFDR); - if (c == 0x82) { /* W83627THF */ - outb_p(0x2b, WDT_EFER); /* select GPIO3 */ - c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ - outb_p(0x2b, WDT_EFER); - outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ - } - outb_p(0x07, WDT_EFER); /* point to logical device number reg */ outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x30, WDT_EFER); /* select CR30 */ @@ -324,7 +311,7 @@ wdt_init(void) spin_lock_init(&io_lock); - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n"); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); @@ -380,5 +367,5 @@ module_exit(wdt_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pádraig Brady "); -MODULE_DESCRIPTION("w83627hf/thf WDT driver"); +MODULE_DESCRIPTION("w83627hf WDT driver"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index eb37fba9b7ef..893dbaf386fb 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -1685,11 +1685,9 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, if (sys_dev) { switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpufreq_add_dev(sys_dev); break; case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: if (unlikely(lock_policy_rwsem_write(cpu))) BUG(); @@ -1701,7 +1699,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, __cpufreq_remove_dev(sys_dev); break; case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: cpufreq_add_dev(sys_dev); break; } diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c index d2f0cbd8b8f3..d1c7cac9316c 100644 --- a/trunk/drivers/cpufreq/cpufreq_stats.c +++ b/trunk/drivers/cpufreq/cpufreq_stats.c @@ -313,11 +313,9 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpufreq_update_policy(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); break; } diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index e678a33ea672..f21fe66c9eef 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -51,31 +51,9 @@ config CRYPTO_DEV_GEODE default m help Say 'Y' here to use the AMD Geode LX processor on-board AES - engine for the CryptoAPI AES algorithm. + engine for the CryptoAPI AES alogrithm. To compile this driver as a module, choose M here: the module will be called geode-aes. -config ZCRYPT - tristate "Support for PCI-attached cryptographic adapters" - depends on S390 - select ZCRYPT_MONOLITHIC if ZCRYPT="y" - 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). - endmenu diff --git a/trunk/drivers/dma/Kconfig b/trunk/drivers/dma/Kconfig index 72be6c63edfc..30d021d1a07c 100644 --- a/trunk/drivers/dma/Kconfig +++ b/trunk/drivers/dma/Kconfig @@ -3,7 +3,6 @@ # menu "DMA Engine support" - depends on !S390 config DMA_ENGINE bool "Support for DMA engines" diff --git a/trunk/drivers/edac/Kconfig b/trunk/drivers/edac/Kconfig index 807c402df049..4f0898400c6d 100644 --- a/trunk/drivers/edac/Kconfig +++ b/trunk/drivers/edac/Kconfig @@ -7,7 +7,6 @@ # menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)' - depends on HAS_IOMEM config EDAC tristate "EDAC core system error reporting (EXPERIMENTAL)" diff --git a/trunk/drivers/firewire/Kconfig b/trunk/drivers/firewire/Kconfig deleted file mode 100644 index 5932c72f9e42..000000000000 --- a/trunk/drivers/firewire/Kconfig +++ /dev/null @@ -1,61 +0,0 @@ -# -*- shell-script -*- - -comment "An alternative FireWire stack is available with EXPERIMENTAL=y" - depends on EXPERIMENTAL=n - -config FIREWIRE - tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)" - depends on EXPERIMENTAL - select CRC_ITU_T - help - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras) to your - computer. - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - To compile this driver as a module, say M here: the module will be - called fw-core. - - This is the "JUJU" FireWire stack, an alternative implementation - designed for robustness and simplicity. You can build either this - stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) - or both. - -config FIREWIRE_OHCI - tristate "Support for OHCI FireWire host controllers" - depends on PCI && FIREWIRE - help - Enable this driver if you have a FireWire controller based - on the OHCI specification. For all practical purposes, this - is the only chipset in use, so say Y here. - - To compile this driver as a module, say M here: The module will be - called fw-ohci. - - If you also build ohci1394 of the classic IEEE 1394 driver stack, - blacklist either ohci1394 or fw-ohci to let hotplug load the desired - driver. - -config FIREWIRE_SBP2 - tristate "Support for storage devices (SBP-2 protocol driver)" - depends on FIREWIRE && SCSI - help - This option enables you to use SBP-2 devices connected to a - FireWire bus. SBP-2 devices include storage devices like - harddisks and DVD drives, also some other FireWire devices - like scanners. - - To compile this driver as a module, say M here: The module will be - called fw-sbp2. - - You should also enable support for disks, CD-ROMs, etc. in the SCSI - configuration section. - - If you also build sbp2 of the classic IEEE 1394 driver stack, - blacklist either sbp2 or fw-sbp2 to let hotplug load the desired - driver. - diff --git a/trunk/drivers/firewire/Makefile b/trunk/drivers/firewire/Makefile deleted file mode 100644 index fc7d59d4bce0..000000000000 --- a/trunk/drivers/firewire/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the Linux IEEE 1394 implementation -# - -fw-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \ - fw-device.o fw-cdev.o - -obj-$(CONFIG_FIREWIRE) += fw-core.o -obj-$(CONFIG_FIREWIRE_OHCI) += fw-ohci.o -obj-$(CONFIG_FIREWIRE_SBP2) += fw-sbp2.o diff --git a/trunk/drivers/firewire/fw-card.c b/trunk/drivers/firewire/fw-card.c deleted file mode 100644 index 636151a64add..000000000000 --- a/trunk/drivers/firewire/fw-card.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -int fw_compute_block_crc(u32 *block) -{ - __be32 be32_block[256]; - int i, length; - - length = (*block >> 16) & 0xff; - for (i = 0; i < length; i++) - be32_block[i] = cpu_to_be32(block[i + 1]); - *block |= crc_itu_t(0, (u8 *) be32_block, length * 4); - - return length; -} - -static DEFINE_MUTEX(card_mutex); -static LIST_HEAD(card_list); - -static LIST_HEAD(descriptor_list); -static int descriptor_count; - -#define BIB_CRC(v) ((v) << 0) -#define BIB_CRC_LENGTH(v) ((v) << 16) -#define BIB_INFO_LENGTH(v) ((v) << 24) - -#define BIB_LINK_SPEED(v) ((v) << 0) -#define BIB_GENERATION(v) ((v) << 4) -#define BIB_MAX_ROM(v) ((v) << 8) -#define BIB_MAX_RECEIVE(v) ((v) << 12) -#define BIB_CYC_CLK_ACC(v) ((v) << 16) -#define BIB_PMC ((1) << 27) -#define BIB_BMC ((1) << 28) -#define BIB_ISC ((1) << 29) -#define BIB_CMC ((1) << 30) -#define BIB_IMC ((1) << 31) - -static u32 * -generate_config_rom(struct fw_card *card, size_t *config_rom_length) -{ - struct fw_descriptor *desc; - static u32 config_rom[256]; - int i, j, length; - - /* - * Initialize contents of config rom buffer. On the OHCI - * controller, block reads to the config rom accesses the host - * memory, but quadlet read access the hardware bus info block - * registers. That's just crack, but it means we should make - * sure the contents of bus info block in host memory mathces - * the version stored in the OHCI registers. - */ - - memset(config_rom, 0, sizeof(config_rom)); - config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0); - config_rom[1] = 0x31333934; - - config_rom[2] = - BIB_LINK_SPEED(card->link_speed) | - BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | - BIB_MAX_ROM(2) | - BIB_MAX_RECEIVE(card->max_receive) | - BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC; - config_rom[3] = card->guid >> 32; - config_rom[4] = card->guid; - - /* Generate root directory. */ - i = 5; - config_rom[i++] = 0; - config_rom[i++] = 0x0c0083c0; /* node capabilities */ - j = i + descriptor_count; - - /* Generate root directory entries for descriptors. */ - list_for_each_entry (desc, &descriptor_list, link) { - if (desc->immediate > 0) - config_rom[i++] = desc->immediate; - config_rom[i] = desc->key | (j - i); - i++; - j += desc->length; - } - - /* Update root directory length. */ - config_rom[5] = (i - 5 - 1) << 16; - - /* End of root directory, now copy in descriptors. */ - list_for_each_entry (desc, &descriptor_list, link) { - memcpy(&config_rom[i], desc->data, desc->length * 4); - i += desc->length; - } - - /* Calculate CRCs for all blocks in the config rom. This - * assumes that CRC length and info length are identical for - * the bus info block, which is always the case for this - * implementation. */ - for (i = 0; i < j; i += length + 1) - length = fw_compute_block_crc(config_rom + i); - - *config_rom_length = j; - - return config_rom; -} - -static void -update_config_roms(void) -{ - struct fw_card *card; - u32 *config_rom; - size_t length; - - list_for_each_entry (card, &card_list, link) { - config_rom = generate_config_rom(card, &length); - card->driver->set_config_rom(card, config_rom, length); - } -} - -int -fw_core_add_descriptor(struct fw_descriptor *desc) -{ - size_t i; - - /* - * Check descriptor is valid; the length of all blocks in the - * descriptor has to add up to exactly the length of the - * block. - */ - i = 0; - while (i < desc->length) - i += (desc->data[i] >> 16) + 1; - - if (i != desc->length) - return -EINVAL; - - mutex_lock(&card_mutex); - - list_add_tail(&desc->link, &descriptor_list); - descriptor_count++; - if (desc->immediate > 0) - descriptor_count++; - update_config_roms(); - - mutex_unlock(&card_mutex); - - return 0; -} -EXPORT_SYMBOL(fw_core_add_descriptor); - -void -fw_core_remove_descriptor(struct fw_descriptor *desc) -{ - mutex_lock(&card_mutex); - - list_del(&desc->link); - descriptor_count--; - if (desc->immediate > 0) - descriptor_count--; - update_config_roms(); - - mutex_unlock(&card_mutex); -} -EXPORT_SYMBOL(fw_core_remove_descriptor); - -static const char gap_count_table[] = { - 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 -}; - -struct bm_data { - struct fw_transaction t; - struct { - __be32 arg; - __be32 data; - } lock; - u32 old; - int rcode; - struct completion done; -}; - -static void -complete_bm_lock(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct bm_data *bmd = data; - - if (rcode == RCODE_COMPLETE) - bmd->old = be32_to_cpu(*(__be32 *) payload); - bmd->rcode = rcode; - complete(&bmd->done); -} - -static void -fw_card_bm_work(struct work_struct *work) -{ - struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root; - struct bm_data bmd; - unsigned long flags; - int root_id, new_root_id, irm_id, gap_count, generation, grace; - int do_reset = 0; - - spin_lock_irqsave(&card->lock, flags); - - generation = card->generation; - root = card->root_node->data; - root_id = card->root_node->node_id; - grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); - - if (card->bm_generation + 1 == generation || - (card->bm_generation != generation && grace)) { - /* - * This first step is to figure out who is IRM and - * then try to become bus manager. If the IRM is not - * well defined (e.g. does not have an active link - * layer or does not responds to our lock request, we - * will have to do a little vigilante bus management. - * In that case, we do a goto into the gap count logic - * so that when we do the reset, we still optimize the - * gap count. That could well save a reset in the - * next generation. - */ - - irm_id = card->irm_node->node_id; - if (!card->irm_node->link_on) { - new_root_id = card->local_node->node_id; - fw_notify("IRM has link off, making local node (%02x) root.\n", - new_root_id); - goto pick_me; - } - - bmd.lock.arg = cpu_to_be32(0x3f); - bmd.lock.data = cpu_to_be32(card->local_node->node_id); - - spin_unlock_irqrestore(&card->lock, flags); - - init_completion(&bmd.done); - fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, - irm_id, generation, - SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - &bmd.lock, sizeof(bmd.lock), - complete_bm_lock, &bmd); - wait_for_completion(&bmd.done); - - if (bmd.rcode == RCODE_GENERATION) { - /* - * Another bus reset happened. Just return, - * the BM work has been rescheduled. - */ - return; - } - - if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) - /* Somebody else is BM, let them do the work. */ - return; - - spin_lock_irqsave(&card->lock, flags); - if (bmd.rcode != RCODE_COMPLETE) { - /* - * The lock request failed, maybe the IRM - * isn't really IRM capable after all. Let's - * do a bus reset and pick the local node as - * root, and thus, IRM. - */ - new_root_id = card->local_node->node_id; - fw_notify("BM lock failed, making local node (%02x) root.\n", - new_root_id); - goto pick_me; - } - } else if (card->bm_generation != generation) { - /* - * OK, we weren't BM in the last generation, and it's - * less than 100ms since last bus reset. Reschedule - * this task 100ms from now. - */ - spin_unlock_irqrestore(&card->lock, flags); - schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); - return; - } - - /* - * We're bus manager for this generation, so next step is to - * make sure we have an active cycle master and do gap count - * optimization. - */ - card->bm_generation = generation; - - if (root == NULL) { - /* - * Either link_on is false, or we failed to read the - * config rom. In either case, pick another root. - */ - new_root_id = card->local_node->node_id; - } else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) { - /* - * If we haven't probed this device yet, bail out now - * and let's try again once that's done. - */ - spin_unlock_irqrestore(&card->lock, flags); - return; - } else if (root->config_rom[2] & BIB_CMC) { - /* - * FIXME: I suppose we should set the cmstr bit in the - * STATE_CLEAR register of this node, as described in - * 1394-1995, 8.4.2.6. Also, send out a force root - * packet for this node. - */ - new_root_id = root_id; - } else { - /* - * Current root has an active link layer and we - * successfully read the config rom, but it's not - * cycle master capable. - */ - new_root_id = card->local_node->node_id; - } - - pick_me: - /* Now figure out what gap count to set. */ - if (card->topology_type == FW_TOPOLOGY_A && - card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) - gap_count = gap_count_table[card->root_node->max_hops]; - else - gap_count = 63; - - /* - * Finally, figure out if we should do a reset or not. If we've - * done less that 5 resets with the same physical topology and we - * have either a new root or a new gap count setting, let's do it. - */ - - if (card->bm_retries++ < 5 && - (card->gap_count != gap_count || new_root_id != root_id)) - do_reset = 1; - - spin_unlock_irqrestore(&card->lock, flags); - - if (do_reset) { - fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", - card->index, new_root_id, gap_count); - fw_send_phy_config(card, new_root_id, generation, gap_count); - fw_core_initiate_bus_reset(card, 1); - } -} - -static void -flush_timer_callback(unsigned long data) -{ - struct fw_card *card = (struct fw_card *)data; - - fw_flush_transactions(card); -} - -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device) -{ - static atomic_t index = ATOMIC_INIT(-1); - - kref_init(&card->kref); - card->index = atomic_inc_return(&index); - card->driver = driver; - card->device = device; - card->current_tlabel = 0; - card->tlabel_mask = 0; - card->color = 0; - - INIT_LIST_HEAD(&card->transaction_list); - spin_lock_init(&card->lock); - setup_timer(&card->flush_timer, - flush_timer_callback, (unsigned long)card); - - card->local_node = NULL; - - INIT_DELAYED_WORK(&card->work, fw_card_bm_work); -} -EXPORT_SYMBOL(fw_card_initialize); - -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid) -{ - u32 *config_rom; - size_t length; - - card->max_receive = max_receive; - card->link_speed = link_speed; - card->guid = guid; - - /* Activate link_on bit and contender bit in our self ID packets.*/ - if (card->driver->update_phy_reg(card, 4, 0, - PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) - return -EIO; - - /* - * The subsystem grabs a reference when the card is added and - * drops it when the driver calls fw_core_remove_card. - */ - fw_card_get(card); - - mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - list_add_tail(&card->link, &card_list); - mutex_unlock(&card_mutex); - - return card->driver->enable(card, config_rom, length); -} -EXPORT_SYMBOL(fw_card_add); - - -/* - * The next few functions implements a dummy driver that use once a - * card driver shuts down an fw_card. This allows the driver to - * cleanly unload, as all IO to the card will be handled by the dummy - * driver instead of calling into the (possibly) unloaded module. The - * dummy driver just fails all IO. - */ - -static int -dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) -{ - BUG(); - return -1; -} - -static int -dummy_update_phy_reg(struct fw_card *card, int address, - int clear_bits, int set_bits) -{ - return -ENODEV; -} - -static int -dummy_set_config_rom(struct fw_card *card, - u32 *config_rom, size_t length) -{ - /* - * We take the card out of card_list before setting the dummy - * driver, so this should never get called. - */ - BUG(); - return -1; -} - -static void -dummy_send_request(struct fw_card *card, struct fw_packet *packet) -{ - packet->callback(packet, card, -ENODEV); -} - -static void -dummy_send_response(struct fw_card *card, struct fw_packet *packet) -{ - packet->callback(packet, card, -ENODEV); -} - -static int -dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) -{ - return -ENOENT; -} - -static int -dummy_enable_phys_dma(struct fw_card *card, - int node_id, int generation) -{ - return -ENODEV; -} - -static struct fw_card_driver dummy_driver = { - .name = "dummy", - .enable = dummy_enable, - .update_phy_reg = dummy_update_phy_reg, - .set_config_rom = dummy_set_config_rom, - .send_request = dummy_send_request, - .cancel_packet = dummy_cancel_packet, - .send_response = dummy_send_response, - .enable_phys_dma = dummy_enable_phys_dma, -}; - -void -fw_core_remove_card(struct fw_card *card) -{ - card->driver->update_phy_reg(card, 4, - PHY_LINK_ACTIVE | PHY_CONTENDER, 0); - fw_core_initiate_bus_reset(card, 1); - - mutex_lock(&card_mutex); - list_del(&card->link); - mutex_unlock(&card_mutex); - - /* Set up the dummy driver. */ - card->driver = &dummy_driver; - - fw_flush_transactions(card); - - fw_destroy_nodes(card); - - fw_card_put(card); -} -EXPORT_SYMBOL(fw_core_remove_card); - -struct fw_card * -fw_card_get(struct fw_card *card) -{ - kref_get(&card->kref); - - return card; -} -EXPORT_SYMBOL(fw_card_get); - -static void -release_card(struct kref *kref) -{ - struct fw_card *card = container_of(kref, struct fw_card, kref); - - kfree(card); -} - -/* - * An assumption for fw_card_put() is that the card driver allocates - * the fw_card struct with kalloc and that it has been shut down - * before the last ref is dropped. - */ -void -fw_card_put(struct fw_card *card) -{ - kref_put(&card->kref, release_card); -} -EXPORT_SYMBOL(fw_card_put); - -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) -{ - int reg = short_reset ? 5 : 1; - int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; - - return card->driver->update_phy_reg(card, reg, 0, bit); -} -EXPORT_SYMBOL(fw_core_initiate_bus_reset); diff --git a/trunk/drivers/firewire/fw-cdev.c b/trunk/drivers/firewire/fw-cdev.c deleted file mode 100644 index 0fa5bd54c6a1..000000000000 --- a/trunk/drivers/firewire/fw-cdev.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Char device for device raw access - * - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -struct client; -struct client_resource { - struct list_head link; - void (*release)(struct client *client, struct client_resource *r); - u32 handle; -}; - -/* - * dequeue_event() just kfree()'s the event, so the event has to be - * the first field in the struct. - */ - -struct event { - struct { void *data; size_t size; } v[2]; - struct list_head link; -}; - -struct bus_reset { - struct event event; - struct fw_cdev_event_bus_reset reset; -}; - -struct response { - struct event event; - struct fw_transaction transaction; - struct client *client; - struct client_resource resource; - struct fw_cdev_event_response response; -}; - -struct iso_interrupt { - struct event event; - struct fw_cdev_event_iso_interrupt interrupt; -}; - -struct client { - u32 version; - struct fw_device *device; - spinlock_t lock; - u32 resource_handle; - struct list_head resource_list; - struct list_head event_list; - wait_queue_head_t wait; - u64 bus_reset_closure; - - struct fw_iso_context *iso_context; - u64 iso_closure; - struct fw_iso_buffer buffer; - unsigned long vm_start; - - struct list_head link; -}; - -static inline void __user * -u64_to_uptr(__u64 value) -{ - return (void __user *)(unsigned long)value; -} - -static inline __u64 -uptr_to_u64(void __user *ptr) -{ - return (__u64)(unsigned long)ptr; -} - -static int fw_device_op_open(struct inode *inode, struct file *file) -{ - struct fw_device *device; - struct client *client; - unsigned long flags; - - device = fw_device_from_devt(inode->i_rdev); - if (device == NULL) - return -ENODEV; - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - - client->device = fw_device_get(device); - INIT_LIST_HEAD(&client->event_list); - INIT_LIST_HEAD(&client->resource_list); - spin_lock_init(&client->lock); - init_waitqueue_head(&client->wait); - - file->private_data = client; - - spin_lock_irqsave(&device->card->lock, flags); - list_add_tail(&client->link, &device->client_list); - spin_unlock_irqrestore(&device->card->lock, flags); - - return 0; -} - -static void queue_event(struct client *client, struct event *event, - void *data0, size_t size0, void *data1, size_t size1) -{ - unsigned long flags; - - event->v[0].data = data0; - event->v[0].size = size0; - event->v[1].data = data1; - event->v[1].size = size1; - - spin_lock_irqsave(&client->lock, flags); - - list_add_tail(&event->link, &client->event_list); - wake_up_interruptible(&client->wait); - - spin_unlock_irqrestore(&client->lock, flags); -} - -static int -dequeue_event(struct client *client, char __user *buffer, size_t count) -{ - unsigned long flags; - struct event *event; - size_t size, total; - int i, retval; - - retval = wait_event_interruptible(client->wait, - !list_empty(&client->event_list) || - fw_device_is_shutdown(client->device)); - if (retval < 0) - return retval; - - if (list_empty(&client->event_list) && - fw_device_is_shutdown(client->device)) - return -ENODEV; - - spin_lock_irqsave(&client->lock, flags); - event = container_of(client->event_list.next, struct event, link); - list_del(&event->link); - spin_unlock_irqrestore(&client->lock, flags); - - total = 0; - for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { - size = min(event->v[i].size, count - total); - if (copy_to_user(buffer + total, event->v[i].data, size)) { - retval = -EFAULT; - goto out; - } - total += size; - } - retval = total; - - out: - kfree(event); - - return retval; -} - -static ssize_t -fw_device_op_read(struct file *file, - char __user *buffer, size_t count, loff_t *offset) -{ - struct client *client = file->private_data; - - return dequeue_event(client, buffer, count); -} - -static void -fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, - struct client *client) -{ - struct fw_card *card = client->device->card; - - event->closure = client->bus_reset_closure; - event->type = FW_CDEV_EVENT_BUS_RESET; - event->node_id = client->device->node_id; - event->local_node_id = card->local_node->node_id; - event->bm_node_id = 0; /* FIXME: We don't track the BM. */ - event->irm_node_id = card->irm_node->node_id; - event->root_node_id = card->root_node->node_id; - event->generation = card->generation; -} - -static void -for_each_client(struct fw_device *device, - void (*callback)(struct client *client)) -{ - struct fw_card *card = device->card; - struct client *c; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - list_for_each_entry(c, &device->client_list, link) - callback(c); - - spin_unlock_irqrestore(&card->lock, flags); -} - -static void -queue_bus_reset_event(struct client *client) -{ - struct bus_reset *bus_reset; - - bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC); - if (bus_reset == NULL) { - fw_notify("Out of memory when allocating bus reset event\n"); - return; - } - - fill_bus_reset_event(&bus_reset->reset, client); - - queue_event(client, &bus_reset->event, - &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0); -} - -void fw_device_cdev_update(struct fw_device *device) -{ - for_each_client(device, queue_bus_reset_event); -} - -static void wake_up_client(struct client *client) -{ - wake_up_interruptible(&client->wait); -} - -void fw_device_cdev_remove(struct fw_device *device) -{ - for_each_client(device, wake_up_client); -} - -static int ioctl_get_info(struct client *client, void *buffer) -{ - struct fw_cdev_get_info *get_info = buffer; - struct fw_cdev_event_bus_reset bus_reset; - - client->version = get_info->version; - get_info->version = FW_CDEV_VERSION; - - if (get_info->rom != 0) { - void __user *uptr = u64_to_uptr(get_info->rom); - size_t want = get_info->rom_length; - size_t have = client->device->config_rom_length * 4; - - if (copy_to_user(uptr, client->device->config_rom, - min(want, have))) - return -EFAULT; - } - get_info->rom_length = client->device->config_rom_length * 4; - - client->bus_reset_closure = get_info->bus_reset_closure; - if (get_info->bus_reset != 0) { - void __user *uptr = u64_to_uptr(get_info->bus_reset); - - fill_bus_reset_event(&bus_reset, client); - if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) - return -EFAULT; - } - - get_info->card = client->device->card->index; - - return 0; -} - -static void -add_client_resource(struct client *client, struct client_resource *resource) -{ - unsigned long flags; - - spin_lock_irqsave(&client->lock, flags); - list_add_tail(&resource->link, &client->resource_list); - resource->handle = client->resource_handle++; - spin_unlock_irqrestore(&client->lock, flags); -} - -static int -release_client_resource(struct client *client, u32 handle, - struct client_resource **resource) -{ - struct client_resource *r; - unsigned long flags; - - spin_lock_irqsave(&client->lock, flags); - list_for_each_entry(r, &client->resource_list, link) { - if (r->handle == handle) { - list_del(&r->link); - break; - } - } - spin_unlock_irqrestore(&client->lock, flags); - - if (&r->link == &client->resource_list) - return -EINVAL; - - if (resource) - *resource = r; - else - r->release(client, r); - - return 0; -} - -static void -release_transaction(struct client *client, struct client_resource *resource) -{ - struct response *response = - container_of(resource, struct response, resource); - - fw_cancel_transaction(client->device->card, &response->transaction); -} - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct response *response = data; - struct client *client = response->client; - unsigned long flags; - - if (length < response->response.length) - response->response.length = length; - if (rcode == RCODE_COMPLETE) - memcpy(response->response.data, payload, - response->response.length); - - spin_lock_irqsave(&client->lock, flags); - list_del(&response->resource.link); - spin_unlock_irqrestore(&client->lock, flags); - - response->response.type = FW_CDEV_EVENT_RESPONSE; - response->response.rcode = rcode; - queue_event(client, &response->event, - &response->response, sizeof(response->response), - response->response.data, response->response.length); -} - -static ssize_t ioctl_send_request(struct client *client, void *buffer) -{ - struct fw_device *device = client->device; - struct fw_cdev_send_request *request = buffer; - struct response *response; - - /* What is the biggest size we'll accept, really? */ - if (request->length > 4096) - return -EINVAL; - - response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL); - if (response == NULL) - return -ENOMEM; - - response->client = client; - response->response.length = request->length; - response->response.closure = request->closure; - - if (request->data && - copy_from_user(response->response.data, - u64_to_uptr(request->data), request->length)) { - kfree(response); - return -EFAULT; - } - - response->resource.release = release_transaction; - add_client_resource(client, &response->resource); - - fw_send_request(device->card, &response->transaction, - request->tcode & 0x1f, - device->node->node_id, - request->generation, - device->node->max_speed, - request->offset, - response->response.data, request->length, - complete_transaction, response); - - if (request->data) - return sizeof(request) + request->length; - else - return sizeof(request); -} - -struct address_handler { - struct fw_address_handler handler; - __u64 closure; - struct client *client; - struct client_resource resource; -}; - -struct request { - struct fw_request *request; - void *data; - size_t length; - struct client_resource resource; -}; - -struct request_event { - struct event event; - struct fw_cdev_event_request request; -}; - -static void -release_request(struct client *client, struct client_resource *resource) -{ - struct request *request = - container_of(resource, struct request, resource); - - fw_send_response(client->device->card, request->request, - RCODE_CONFLICT_ERROR); - kfree(request); -} - -static void -handle_request(struct fw_card *card, struct fw_request *r, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - struct address_handler *handler = callback_data; - struct request *request; - struct request_event *e; - struct client *client = handler->client; - - request = kmalloc(sizeof(*request), GFP_ATOMIC); - e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (request == NULL || e == NULL) { - kfree(request); - kfree(e); - fw_send_response(card, r, RCODE_CONFLICT_ERROR); - return; - } - - request->request = r; - request->data = payload; - request->length = length; - - request->resource.release = release_request; - add_client_resource(client, &request->resource); - - e->request.type = FW_CDEV_EVENT_REQUEST; - e->request.tcode = tcode; - e->request.offset = offset; - e->request.length = length; - e->request.handle = request->resource.handle; - e->request.closure = handler->closure; - - queue_event(client, &e->event, - &e->request, sizeof(e->request), payload, length); -} - -static void -release_address_handler(struct client *client, - struct client_resource *resource) -{ - struct address_handler *handler = - container_of(resource, struct address_handler, resource); - - fw_core_remove_address_handler(&handler->handler); - kfree(handler); -} - -static int ioctl_allocate(struct client *client, void *buffer) -{ - struct fw_cdev_allocate *request = buffer; - struct address_handler *handler; - struct fw_address_region region; - - handler = kmalloc(sizeof(*handler), GFP_KERNEL); - if (handler == NULL) - return -ENOMEM; - - region.start = request->offset; - region.end = request->offset + request->length; - handler->handler.length = request->length; - handler->handler.address_callback = handle_request; - handler->handler.callback_data = handler; - handler->closure = request->closure; - handler->client = client; - - if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { - kfree(handler); - return -EBUSY; - } - - handler->resource.release = release_address_handler; - add_client_resource(client, &handler->resource); - request->handle = handler->resource.handle; - - return 0; -} - -static int ioctl_deallocate(struct client *client, void *buffer) -{ - struct fw_cdev_deallocate *request = buffer; - - return release_client_resource(client, request->handle, NULL); -} - -static int ioctl_send_response(struct client *client, void *buffer) -{ - struct fw_cdev_send_response *request = buffer; - struct client_resource *resource; - struct request *r; - - if (release_client_resource(client, request->handle, &resource) < 0) - return -EINVAL; - r = container_of(resource, struct request, resource); - if (request->length < r->length) - r->length = request->length; - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) - return -EFAULT; - - fw_send_response(client->device->card, r->request, request->rcode); - kfree(r); - - return 0; -} - -static int ioctl_initiate_bus_reset(struct client *client, void *buffer) -{ - struct fw_cdev_initiate_bus_reset *request = buffer; - int short_reset; - - short_reset = (request->type == FW_CDEV_SHORT_RESET); - - return fw_core_initiate_bus_reset(client->device->card, short_reset); -} - -struct descriptor { - struct fw_descriptor d; - struct client_resource resource; - u32 data[0]; -}; - -static void release_descriptor(struct client *client, - struct client_resource *resource) -{ - struct descriptor *descriptor = - container_of(resource, struct descriptor, resource); - - fw_core_remove_descriptor(&descriptor->d); - kfree(descriptor); -} - -static int ioctl_add_descriptor(struct client *client, void *buffer) -{ - struct fw_cdev_add_descriptor *request = buffer; - struct descriptor *descriptor; - int retval; - - if (request->length > 256) - return -EINVAL; - - descriptor = - kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL); - if (descriptor == NULL) - return -ENOMEM; - - if (copy_from_user(descriptor->data, - u64_to_uptr(request->data), request->length * 4)) { - kfree(descriptor); - return -EFAULT; - } - - descriptor->d.length = request->length; - descriptor->d.immediate = request->immediate; - descriptor->d.key = request->key; - descriptor->d.data = descriptor->data; - - retval = fw_core_add_descriptor(&descriptor->d); - if (retval < 0) { - kfree(descriptor); - return retval; - } - - descriptor->resource.release = release_descriptor; - add_client_resource(client, &descriptor->resource); - request->handle = descriptor->resource.handle; - - return 0; -} - -static int ioctl_remove_descriptor(struct client *client, void *buffer) -{ - struct fw_cdev_remove_descriptor *request = buffer; - - return release_client_resource(client, request->handle, NULL); -} - -static void -iso_callback(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *data) -{ - struct client *client = data; - struct iso_interrupt *interrupt; - - interrupt = kzalloc(sizeof(*interrupt) + header_length, GFP_ATOMIC); - if (interrupt == NULL) - return; - - interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; - interrupt->interrupt.closure = client->iso_closure; - interrupt->interrupt.cycle = cycle; - interrupt->interrupt.header_length = header_length; - memcpy(interrupt->interrupt.header, header, header_length); - queue_event(client, &interrupt->event, - &interrupt->interrupt, - sizeof(interrupt->interrupt) + header_length, NULL, 0); -} - -static int ioctl_create_iso_context(struct client *client, void *buffer) -{ - struct fw_cdev_create_iso_context *request = buffer; - - if (request->channel > 63) - return -EINVAL; - - switch (request->type) { - case FW_ISO_CONTEXT_RECEIVE: - if (request->header_size < 4 || (request->header_size & 3)) - return -EINVAL; - - break; - - case FW_ISO_CONTEXT_TRANSMIT: - if (request->speed > SCODE_3200) - return -EINVAL; - - break; - - default: - return -EINVAL; - } - - client->iso_closure = request->closure; - client->iso_context = fw_iso_context_create(client->device->card, - request->type, - request->channel, - request->speed, - request->header_size, - iso_callback, client); - if (IS_ERR(client->iso_context)) - return PTR_ERR(client->iso_context); - - /* We only support one context at this time. */ - request->handle = 0; - - return 0; -} - -static int ioctl_queue_iso(struct client *client, void *buffer) -{ - struct fw_cdev_queue_iso *request = buffer; - struct fw_cdev_iso_packet __user *p, *end, *next; - struct fw_iso_context *ctx = client->iso_context; - unsigned long payload, buffer_end, header_length; - int count; - struct { - struct fw_iso_packet packet; - u8 header[256]; - } u; - - if (ctx == NULL || request->handle != 0) - return -EINVAL; - - /* - * If the user passes a non-NULL data pointer, has mmap()'ed - * the iso buffer, and the pointer points inside the buffer, - * we setup the payload pointers accordingly. Otherwise we - * set them both to 0, which will still let packets with - * payload_length == 0 through. In other words, if no packets - * use the indirect payload, the iso buffer need not be mapped - * and the request->data pointer is ignored. - */ - - payload = (unsigned long)request->data - client->vm_start; - buffer_end = client->buffer.page_count << PAGE_SHIFT; - if (request->data == 0 || client->buffer.pages == NULL || - payload >= buffer_end) { - payload = 0; - buffer_end = 0; - } - - if (!access_ok(VERIFY_READ, request->packets, request->size)) - return -EFAULT; - - p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets); - end = (void __user *)p + request->size; - count = 0; - while (p < end) { - if (__copy_from_user(&u.packet, p, sizeof(*p))) - return -EFAULT; - - if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { - header_length = u.packet.header_length; - } else { - /* - * We require that header_length is a multiple of - * the fixed header size, ctx->header_size. - */ - if (ctx->header_size == 0) { - if (u.packet.header_length > 0) - return -EINVAL; - } else if (u.packet.header_length % ctx->header_size != 0) { - return -EINVAL; - } - header_length = 0; - } - - next = (struct fw_cdev_iso_packet __user *) - &p->header[header_length / 4]; - if (next > end) - return -EINVAL; - if (__copy_from_user - (u.packet.header, p->header, header_length)) - return -EFAULT; - if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && - u.packet.header_length + u.packet.payload_length > 0) - return -EINVAL; - if (payload + u.packet.payload_length > buffer_end) - return -EINVAL; - - if (fw_iso_context_queue(ctx, &u.packet, - &client->buffer, payload)) - break; - - p = next; - payload += u.packet.payload_length; - count++; - } - - request->size -= uptr_to_u64(p) - request->packets; - request->packets = uptr_to_u64(p); - request->data = client->vm_start + payload; - - return count; -} - -static int ioctl_start_iso(struct client *client, void *buffer) -{ - struct fw_cdev_start_iso *request = buffer; - - if (request->handle != 0) - return -EINVAL; - if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { - if (request->tags == 0 || request->tags > 15) - return -EINVAL; - - if (request->sync > 15) - return -EINVAL; - } - - return fw_iso_context_start(client->iso_context, request->cycle, - request->sync, request->tags); -} - -static int ioctl_stop_iso(struct client *client, void *buffer) -{ - struct fw_cdev_stop_iso *request = buffer; - - if (request->handle != 0) - return -EINVAL; - - return fw_iso_context_stop(client->iso_context); -} - -static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { - ioctl_get_info, - ioctl_send_request, - ioctl_allocate, - ioctl_deallocate, - ioctl_send_response, - ioctl_initiate_bus_reset, - ioctl_add_descriptor, - ioctl_remove_descriptor, - ioctl_create_iso_context, - ioctl_queue_iso, - ioctl_start_iso, - ioctl_stop_iso, -}; - -static int -dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) -{ - char buffer[256]; - int retval; - - if (_IOC_TYPE(cmd) != '#' || - _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) - return -EINVAL; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_from_user(buffer, arg, _IOC_SIZE(cmd))) - return -EFAULT; - } - - retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); - if (retval < 0) - return retval; - - if (_IOC_DIR(cmd) & _IOC_READ) { - if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_to_user(arg, buffer, _IOC_SIZE(cmd))) - return -EFAULT; - } - - return 0; -} - -static long -fw_device_op_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct client *client = file->private_data; - - return dispatch_ioctl(client, cmd, (void __user *) arg); -} - -#ifdef CONFIG_COMPAT -static long -fw_device_op_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct client *client = file->private_data; - - return dispatch_ioctl(client, cmd, compat_ptr(arg)); -} -#endif - -static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct client *client = file->private_data; - enum dma_data_direction direction; - unsigned long size; - int page_count, retval; - - /* FIXME: We could support multiple buffers, but we don't. */ - if (client->buffer.pages != NULL) - return -EBUSY; - - if (!(vma->vm_flags & VM_SHARED)) - return -EINVAL; - - if (vma->vm_start & ~PAGE_MASK) - return -EINVAL; - - client->vm_start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - page_count = size >> PAGE_SHIFT; - if (size & ~PAGE_MASK) - return -EINVAL; - - if (vma->vm_flags & VM_WRITE) - direction = DMA_TO_DEVICE; - else - direction = DMA_FROM_DEVICE; - - retval = fw_iso_buffer_init(&client->buffer, client->device->card, - page_count, direction); - if (retval < 0) - return retval; - - retval = fw_iso_buffer_map(&client->buffer, vma); - if (retval < 0) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - - return retval; -} - -static int fw_device_op_release(struct inode *inode, struct file *file) -{ - struct client *client = file->private_data; - struct event *e, *next_e; - struct client_resource *r, *next_r; - unsigned long flags; - - if (client->buffer.pages) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - - if (client->iso_context) - fw_iso_context_destroy(client->iso_context); - - list_for_each_entry_safe(r, next_r, &client->resource_list, link) - r->release(client, r); - - /* - * FIXME: We should wait for the async tasklets to stop - * running before freeing the memory. - */ - - list_for_each_entry_safe(e, next_e, &client->event_list, link) - kfree(e); - - spin_lock_irqsave(&client->device->card->lock, flags); - list_del(&client->link); - spin_unlock_irqrestore(&client->device->card->lock, flags); - - fw_device_put(client->device); - kfree(client); - - return 0; -} - -static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) -{ - struct client *client = file->private_data; - unsigned int mask = 0; - - poll_wait(file, &client->wait, pt); - - if (fw_device_is_shutdown(client->device)) - mask |= POLLHUP | POLLERR; - if (!list_empty(&client->event_list)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -const struct file_operations fw_device_ops = { - .owner = THIS_MODULE, - .open = fw_device_op_open, - .read = fw_device_op_read, - .unlocked_ioctl = fw_device_op_ioctl, - .poll = fw_device_op_poll, - .release = fw_device_op_release, - .mmap = fw_device_op_mmap, - -#ifdef CONFIG_COMPAT - .compat_ioctl = fw_device_op_compat_ioctl, -#endif -}; diff --git a/trunk/drivers/firewire/fw-device.c b/trunk/drivers/firewire/fw-device.c deleted file mode 100644 index c1ce465d9710..000000000000 --- a/trunk/drivers/firewire/fw-device.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Device probing and sysfs code. - * - * Copyright (C) 2005-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) -{ - ci->p = p + 1; - ci->end = ci->p + (p[0] >> 16); -} -EXPORT_SYMBOL(fw_csr_iterator_init); - -int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) -{ - *key = *ci->p >> 24; - *value = *ci->p & 0xffffff; - - return ci->p++ < ci->end; -} -EXPORT_SYMBOL(fw_csr_iterator_next); - -static int is_fw_unit(struct device *dev); - -static int match_unit_directory(u32 * directory, const struct fw_device_id *id) -{ - struct fw_csr_iterator ci; - int key, value, match; - - match = 0; - fw_csr_iterator_init(&ci, directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (key == CSR_VENDOR && value == id->vendor) - match |= FW_MATCH_VENDOR; - if (key == CSR_MODEL && value == id->model) - match |= FW_MATCH_MODEL; - if (key == CSR_SPECIFIER_ID && value == id->specifier_id) - match |= FW_MATCH_SPECIFIER_ID; - if (key == CSR_VERSION && value == id->version) - match |= FW_MATCH_VERSION; - } - - return (match & id->match_flags) == id->match_flags; -} - -static int fw_unit_match(struct device *dev, struct device_driver *drv) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_driver *driver = fw_driver(drv); - int i; - - /* We only allow binding to fw_units. */ - if (!is_fw_unit(dev)) - return 0; - - for (i = 0; driver->id_table[i].match_flags != 0; i++) { - if (match_unit_directory(unit->directory, &driver->id_table[i])) - return 1; - } - - return 0; -} - -static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct fw_csr_iterator ci; - - int key, value; - int vendor = 0; - int model = 0; - int specifier_id = 0; - int version = 0; - - fw_csr_iterator_init(&ci, &device->config_rom[5]); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_VENDOR: - vendor = value; - break; - case CSR_MODEL: - model = value; - break; - } - } - - fw_csr_iterator_init(&ci, unit->directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_SPECIFIER_ID: - specifier_id = value; - break; - case CSR_VERSION: - version = value; - break; - } - } - - return snprintf(buffer, buffer_size, - "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", - vendor, model, specifier_id, version); -} - -static int -fw_unit_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct fw_unit *unit = fw_unit(dev); - char modalias[64]; - int length = 0; - int i = 0; - - get_modalias(unit, modalias, sizeof(modalias)); - - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=%s", modalias)) - return -ENOMEM; - - envp[i] = NULL; - - return 0; -} - -struct bus_type fw_bus_type = { - .name = "firewire", - .match = fw_unit_match, -}; -EXPORT_SYMBOL(fw_bus_type); - -struct fw_device *fw_device_get(struct fw_device *device) -{ - get_device(&device->device); - - return device; -} - -void fw_device_put(struct fw_device *device) -{ - put_device(&device->device); -} - -static void fw_device_release(struct device *dev) -{ - struct fw_device *device = fw_device(dev); - unsigned long flags; - - /* - * Take the card lock so we don't set this to NULL while a - * FW_NODE_UPDATED callback is being handled. - */ - spin_lock_irqsave(&device->card->lock, flags); - device->node->data = NULL; - spin_unlock_irqrestore(&device->card->lock, flags); - - fw_node_put(device->node); - fw_card_put(device->card); - kfree(device->config_rom); - kfree(device); -} - -int fw_device_enable_phys_dma(struct fw_device *device) -{ - return device->card->driver->enable_phys_dma(device->card, - device->node_id, - device->generation); -} -EXPORT_SYMBOL(fw_device_enable_phys_dma); - -struct config_rom_attribute { - struct device_attribute attr; - u32 key; -}; - -static ssize_t -show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) -{ - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); - struct fw_csr_iterator ci; - u32 *dir; - int key, value; - - if (is_fw_unit(dev)) - dir = fw_unit(dev)->directory; - else - dir = fw_device(dev)->config_rom + 5; - - fw_csr_iterator_init(&ci, dir); - while (fw_csr_iterator_next(&ci, &key, &value)) - if (attr->key == key) - return snprintf(buf, buf ? PAGE_SIZE : 0, - "0x%06x\n", value); - - return -ENOENT; -} - -#define IMMEDIATE_ATTR(name, key) \ - { __ATTR(name, S_IRUGO, show_immediate, NULL), key } - -static ssize_t -show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf) -{ - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); - struct fw_csr_iterator ci; - u32 *dir, *block = NULL, *p, *end; - int length, key, value, last_key = 0; - char *b; - - if (is_fw_unit(dev)) - dir = fw_unit(dev)->directory; - else - dir = fw_device(dev)->config_rom + 5; - - fw_csr_iterator_init(&ci, dir); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (attr->key == last_key && - key == (CSR_DESCRIPTOR | CSR_LEAF)) - block = ci.p - 1 + value; - last_key = key; - } - - if (block == NULL) - return -ENOENT; - - length = min(block[0] >> 16, 256U); - if (length < 3) - return -ENOENT; - - if (block[1] != 0 || block[2] != 0) - /* Unknown encoding. */ - return -ENOENT; - - if (buf == NULL) - return length * 4; - - b = buf; - end = &block[length + 1]; - for (p = &block[3]; p < end; p++, b += 4) - * (u32 *) b = (__force u32) __cpu_to_be32(*p); - - /* Strip trailing whitespace and add newline. */ - while (b--, (isspace(*b) || *b == '\0') && b > buf); - strcpy(b + 1, "\n"); - - return b + 2 - buf; -} - -#define TEXT_LEAF_ATTR(name, key) \ - { __ATTR(name, S_IRUGO, show_text_leaf, NULL), key } - -static struct config_rom_attribute config_rom_attributes[] = { - IMMEDIATE_ATTR(vendor, CSR_VENDOR), - IMMEDIATE_ATTR(hardware_version, CSR_HARDWARE_VERSION), - IMMEDIATE_ATTR(specifier_id, CSR_SPECIFIER_ID), - IMMEDIATE_ATTR(version, CSR_VERSION), - IMMEDIATE_ATTR(model, CSR_MODEL), - TEXT_LEAF_ATTR(vendor_name, CSR_VENDOR), - TEXT_LEAF_ATTR(model_name, CSR_MODEL), - TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), -}; - -static void -init_fw_attribute_group(struct device *dev, - struct device_attribute *attrs, - struct fw_attribute_group *group) -{ - struct device_attribute *attr; - int i, j; - - for (j = 0; attrs[j].attr.name != NULL; j++) - group->attrs[j] = &attrs[j].attr; - - for (i = 0; i < ARRAY_SIZE(config_rom_attributes); i++) { - attr = &config_rom_attributes[i].attr; - if (attr->show(dev, attr, NULL) < 0) - continue; - group->attrs[j++] = &attr->attr; - } - - BUG_ON(j >= ARRAY_SIZE(group->attrs)); - group->attrs[j++] = NULL; - group->groups[0] = &group->group; - group->groups[1] = NULL; - group->group.attrs = group->attrs; - dev->groups = group->groups; -} - -static ssize_t -modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fw_unit *unit = fw_unit(dev); - int length; - - length = get_modalias(unit, buf, PAGE_SIZE); - strcpy(buf + length, "\n"); - - return length + 1; -} - -static ssize_t -rom_index_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev->parent); - struct fw_unit *unit = fw_unit(dev); - - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)(unit->directory - device->config_rom)); -} - -static struct device_attribute fw_unit_attributes[] = { - __ATTR_RO(modalias), - __ATTR_RO(rom_index), - __ATTR_NULL, -}; - -static ssize_t -config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev); - - memcpy(buf, device->config_rom, device->config_rom_length * 4); - - return device->config_rom_length * 4; -} - -static ssize_t -guid_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev); - u64 guid; - - guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4]; - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)guid); -} - -static struct device_attribute fw_device_attributes[] = { - __ATTR_RO(config_rom), - __ATTR_RO(guid), - __ATTR_NULL, -}; - -struct read_quadlet_callback_data { - struct completion done; - int rcode; - u32 data; -}; - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct read_quadlet_callback_data *callback_data = data; - - if (rcode == RCODE_COMPLETE) - callback_data->data = be32_to_cpu(*(__be32 *)payload); - callback_data->rcode = rcode; - complete(&callback_data->done); -} - -static int read_rom(struct fw_device *device, int index, u32 * data) -{ - struct read_quadlet_callback_data callback_data; - struct fw_transaction t; - u64 offset; - - init_completion(&callback_data.done); - - offset = 0xfffff0000400ULL + index * 4; - fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, - device->node_id, - device->generation, SCODE_100, - offset, NULL, 4, complete_transaction, &callback_data); - - wait_for_completion(&callback_data.done); - - *data = callback_data.data; - - return callback_data.rcode; -} - -static int read_bus_info_block(struct fw_device *device) -{ - static u32 rom[256]; - u32 stack[16], sp, key; - int i, end, length; - - /* First read the bus info block. */ - for (i = 0; i < 5; i++) { - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - /* - * As per IEEE1212 7.2, during power-up, devices can - * reply with a 0 for the first quadlet of the config - * rom to indicate that they are booting (for example, - * if the firmware is on the disk of a external - * harddisk). In that case we just fail, and the - * retry mechanism will try again later. - */ - if (i == 0 && rom[i] == 0) - return -1; - } - - /* - * Now parse the config rom. The config rom is a recursive - * directory structure so we parse it using a stack of - * references to the blocks that make up the structure. We - * push a reference to the root directory on the stack to - * start things off. - */ - length = i; - sp = 0; - stack[sp++] = 0xc0000005; - while (sp > 0) { - /* - * Pop the next block reference of the stack. The - * lower 24 bits is the offset into the config rom, - * the upper 8 bits are the type of the reference the - * block. - */ - key = stack[--sp]; - i = key & 0xffffff; - if (i >= ARRAY_SIZE(rom)) - /* - * The reference points outside the standard - * config rom area, something's fishy. - */ - return -1; - - /* Read header quadlet for the block to get the length. */ - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - end = i + (rom[i] >> 16) + 1; - i++; - if (end > ARRAY_SIZE(rom)) - /* - * This block extends outside standard config - * area (and the array we're reading it - * into). That's broken, so ignore this - * device. - */ - return -1; - - /* - * Now read in the block. If this is a directory - * block, check the entries as we read them to see if - * it references another block, and push it in that case. - */ - while (i < end) { - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && - sp < ARRAY_SIZE(stack)) - stack[sp++] = i + rom[i]; - i++; - } - if (length < i) - length = i; - } - - device->config_rom = kmalloc(length * 4, GFP_KERNEL); - if (device->config_rom == NULL) - return -1; - memcpy(device->config_rom, rom, length * 4); - device->config_rom_length = length; - - return 0; -} - -static void fw_unit_release(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - - kfree(unit); -} - -static struct device_type fw_unit_type = { - .uevent = fw_unit_uevent, - .release = fw_unit_release, -}; - -static int is_fw_unit(struct device *dev) -{ - return dev->type == &fw_unit_type; -} - -static void create_units(struct fw_device *device) -{ - struct fw_csr_iterator ci; - struct fw_unit *unit; - int key, value, i; - - i = 0; - fw_csr_iterator_init(&ci, &device->config_rom[5]); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (key != (CSR_UNIT | CSR_DIRECTORY)) - continue; - - /* - * Get the address of the unit directory and try to - * match the drivers id_tables against it. - */ - unit = kzalloc(sizeof(*unit), GFP_KERNEL); - if (unit == NULL) { - fw_error("failed to allocate memory for unit\n"); - continue; - } - - unit->directory = ci.p + value - 1; - unit->device.bus = &fw_bus_type; - unit->device.type = &fw_unit_type; - unit->device.parent = &device->device; - snprintf(unit->device.bus_id, sizeof(unit->device.bus_id), - "%s.%d", device->device.bus_id, i++); - - init_fw_attribute_group(&unit->device, - fw_unit_attributes, - &unit->attribute_group); - if (device_register(&unit->device) < 0) - goto skip_unit; - - continue; - - skip_unit: - kfree(unit); - } -} - -static int shutdown_unit(struct device *device, void *data) -{ - device_unregister(device); - - return 0; -} - -static DECLARE_RWSEM(idr_rwsem); -static DEFINE_IDR(fw_device_idr); -int fw_cdev_major; - -struct fw_device *fw_device_from_devt(dev_t devt) -{ - struct fw_device *device; - - down_read(&idr_rwsem); - device = idr_find(&fw_device_idr, MINOR(devt)); - up_read(&idr_rwsem); - - return device; -} - -static void fw_device_shutdown(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - int minor = MINOR(device->device.devt); - - down_write(&idr_rwsem); - idr_remove(&fw_device_idr, minor); - up_write(&idr_rwsem); - - fw_device_cdev_remove(device); - device_for_each_child(&device->device, NULL, shutdown_unit); - device_unregister(&device->device); -} - -static struct device_type fw_device_type = { - .release = fw_device_release, -}; - -/* - * These defines control the retry behavior for reading the config - * rom. It shouldn't be necessary to tweak these; if the device - * doesn't respond to a config rom read within 10 seconds, it's not - * going to respond at all. As for the initial delay, a lot of - * devices will be able to respond within half a second after bus - * reset. On the other hand, it's not really worth being more - * aggressive than that, since it scales pretty well; if 10 devices - * are plugged in, they're all getting read within one second. - */ - -#define MAX_RETRIES 10 -#define RETRY_DELAY (3 * HZ) -#define INITIAL_DELAY (HZ / 2) - -static void fw_device_init(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - int minor, err; - - /* - * All failure paths here set node->data to NULL, so that we - * don't try to do device_for_each_child() on a kfree()'d - * device. - */ - - if (read_bus_info_block(device) < 0) { - if (device->config_rom_retries < MAX_RETRIES) { - device->config_rom_retries++; - schedule_delayed_work(&device->work, RETRY_DELAY); - } else { - fw_notify("giving up on config rom for node id %x\n", - device->node_id); - if (device->node == device->card->root_node) - schedule_delayed_work(&device->card->work, 0); - fw_device_release(&device->device); - } - return; - } - - err = -ENOMEM; - down_write(&idr_rwsem); - if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) - err = idr_get_new(&fw_device_idr, device, &minor); - up_write(&idr_rwsem); - if (err < 0) - goto error; - - device->device.bus = &fw_bus_type; - device->device.type = &fw_device_type; - device->device.parent = device->card->device; - device->device.devt = MKDEV(fw_cdev_major, minor); - snprintf(device->device.bus_id, sizeof(device->device.bus_id), - "fw%d", minor); - - init_fw_attribute_group(&device->device, - fw_device_attributes, - &device->attribute_group); - if (device_add(&device->device)) { - fw_error("Failed to add device.\n"); - goto error_with_cdev; - } - - create_units(device); - - /* - * Transition the device to running state. If it got pulled - * out from under us while we did the intialization work, we - * have to shut down the device again here. Normally, though, - * fw_node_event will be responsible for shutting it down when - * necessary. We have to use the atomic cmpxchg here to avoid - * racing with the FW_NODE_DESTROYED case in - * fw_node_event(). - */ - if (atomic_cmpxchg(&device->state, - FW_DEVICE_INITIALIZING, - FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) - fw_device_shutdown(&device->work.work); - else - fw_notify("created new fw device %s (%d config rom retries)\n", - device->device.bus_id, device->config_rom_retries); - - /* - * Reschedule the IRM work if we just finished reading the - * root node config rom. If this races with a bus reset we - * just end up running the IRM work a couple of extra times - - * pretty harmless. - */ - if (device->node == device->card->root_node) - schedule_delayed_work(&device->card->work, 0); - - return; - - error_with_cdev: - down_write(&idr_rwsem); - idr_remove(&fw_device_idr, minor); - up_write(&idr_rwsem); - error: - put_device(&device->device); -} - -static int update_unit(struct device *dev, void *data) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_driver *driver = (struct fw_driver *)dev->driver; - - if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { - down(&dev->sem); - driver->update(unit); - up(&dev->sem); - } - - return 0; -} - -static void fw_device_update(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - - fw_device_cdev_update(device); - device_for_each_child(&device->device, NULL, update_unit); -} - -void fw_node_event(struct fw_card *card, struct fw_node *node, int event) -{ - struct fw_device *device; - - switch (event) { - case FW_NODE_CREATED: - case FW_NODE_LINK_ON: - if (!node->link_on) - break; - - device = kzalloc(sizeof(*device), GFP_ATOMIC); - if (device == NULL) - break; - - /* - * Do minimal intialization of the device here, the - * rest will happen in fw_device_init(). We need the - * card and node so we can read the config rom and we - * need to do device_initialize() now so - * device_for_each_child() in FW_NODE_UPDATED is - * doesn't freak out. - */ - device_initialize(&device->device); - atomic_set(&device->state, FW_DEVICE_INITIALIZING); - device->card = fw_card_get(card); - device->node = fw_node_get(node); - device->node_id = node->node_id; - device->generation = card->generation; - INIT_LIST_HEAD(&device->client_list); - - /* - * Set the node data to point back to this device so - * FW_NODE_UPDATED callbacks can update the node_id - * and generation for the device. - */ - node->data = device; - - /* - * Many devices are slow to respond after bus resets, - * especially if they are bus powered and go through - * power-up after getting plugged in. We schedule the - * first config rom scan half a second after bus reset. - */ - INIT_DELAYED_WORK(&device->work, fw_device_init); - schedule_delayed_work(&device->work, INITIAL_DELAY); - break; - - case FW_NODE_UPDATED: - if (!node->link_on || node->data == NULL) - break; - - device = node->data; - device->node_id = node->node_id; - device->generation = card->generation; - if (atomic_read(&device->state) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_update); - schedule_delayed_work(&device->work, 0); - } - break; - - case FW_NODE_DESTROYED: - case FW_NODE_LINK_OFF: - if (!node->data) - break; - - /* - * Destroy the device associated with the node. There - * are two cases here: either the device is fully - * initialized (FW_DEVICE_RUNNING) or we're in the - * process of reading its config rom - * (FW_DEVICE_INITIALIZING). If it is fully - * initialized we can reuse device->work to schedule a - * full fw_device_shutdown(). If not, there's work - * scheduled to read it's config rom, and we just put - * the device in shutdown state to have that code fail - * to create the device. - */ - device = node->data; - if (atomic_xchg(&device->state, - FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); - schedule_delayed_work(&device->work, 0); - } - break; - } -} diff --git a/trunk/drivers/firewire/fw-device.h b/trunk/drivers/firewire/fw-device.h deleted file mode 100644 index 0ba9d64ccf4c..000000000000 --- a/trunk/drivers/firewire/fw-device.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2005-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 __fw_device_h -#define __fw_device_h - -#include -#include -#include - -enum fw_device_state { - FW_DEVICE_INITIALIZING, - FW_DEVICE_RUNNING, - FW_DEVICE_SHUTDOWN, -}; - -struct fw_attribute_group { - struct attribute_group *groups[2]; - struct attribute_group group; - struct attribute *attrs[11]; -}; - -struct fw_device { - atomic_t state; - struct fw_node *node; - int node_id; - int generation; - struct fw_card *card; - struct device device; - struct list_head link; - struct list_head client_list; - u32 *config_rom; - size_t config_rom_length; - int config_rom_retries; - struct delayed_work work; - struct fw_attribute_group attribute_group; -}; - -static inline struct fw_device * -fw_device(struct device *dev) -{ - return container_of(dev, struct fw_device, device); -} - -static inline int -fw_device_is_shutdown(struct fw_device *device) -{ - return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN; -} - -struct fw_device *fw_device_get(struct fw_device *device); -void fw_device_put(struct fw_device *device); -int fw_device_enable_phys_dma(struct fw_device *device); - -void fw_device_cdev_update(struct fw_device *device); -void fw_device_cdev_remove(struct fw_device *device); - -struct fw_device *fw_device_from_devt(dev_t devt); -extern int fw_cdev_major; - -struct fw_unit { - struct device device; - u32 *directory; - struct fw_attribute_group attribute_group; -}; - -static inline struct fw_unit * -fw_unit(struct device *dev) -{ - return container_of(dev, struct fw_unit, device); -} - -#define CSR_OFFSET 0x40 -#define CSR_LEAF 0x80 -#define CSR_DIRECTORY 0xc0 - -#define CSR_DESCRIPTOR 0x01 -#define CSR_VENDOR 0x03 -#define CSR_HARDWARE_VERSION 0x04 -#define CSR_NODE_CAPABILITIES 0x0c -#define CSR_UNIT 0x11 -#define CSR_SPECIFIER_ID 0x12 -#define CSR_VERSION 0x13 -#define CSR_DEPENDENT_INFO 0x14 -#define CSR_MODEL 0x17 -#define CSR_INSTANCE 0x18 - -#define SBP2_COMMAND_SET_SPECIFIER 0x38 -#define SBP2_COMMAND_SET 0x39 -#define SBP2_COMMAND_SET_REVISION 0x3b -#define SBP2_FIRMWARE_REVISION 0x3c - -struct fw_csr_iterator { - u32 *p; - u32 *end; -}; - -void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p); -int fw_csr_iterator_next(struct fw_csr_iterator *ci, - int *key, int *value); - -#define FW_MATCH_VENDOR 0x0001 -#define FW_MATCH_MODEL 0x0002 -#define FW_MATCH_SPECIFIER_ID 0x0004 -#define FW_MATCH_VERSION 0x0008 - -struct fw_device_id { - u32 match_flags; - u32 vendor; - u32 model; - u32 specifier_id; - u32 version; - void *driver_data; -}; - -struct fw_driver { - struct device_driver driver; - /* Called when the parent device sits through a bus reset. */ - void (*update) (struct fw_unit *unit); - const struct fw_device_id *id_table; -}; - -static inline struct fw_driver * -fw_driver(struct device_driver *drv) -{ - return container_of(drv, struct fw_driver, driver); -} - -extern const struct file_operations fw_device_ops; - -#endif /* __fw_device_h */ diff --git a/trunk/drivers/firewire/fw-iso.c b/trunk/drivers/firewire/fw-iso.c deleted file mode 100644 index 2b640e9be6de..000000000000 --- a/trunk/drivers/firewire/fw-iso.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Isochronous IO functionality - * - * Copyright (C) 2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, - int page_count, enum dma_data_direction direction) -{ - int i, j, retval = -ENOMEM; - dma_addr_t address; - - buffer->page_count = page_count; - buffer->direction = direction; - - buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]), - GFP_KERNEL); - if (buffer->pages == NULL) - goto out; - - for (i = 0; i < buffer->page_count; i++) { - buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); - if (buffer->pages[i] == NULL) - goto out_pages; - - address = dma_map_page(card->device, buffer->pages[i], - 0, PAGE_SIZE, direction); - if (dma_mapping_error(address)) { - __free_page(buffer->pages[i]); - goto out_pages; - } - set_page_private(buffer->pages[i], address); - } - - return 0; - - out_pages: - for (j = 0; j < i; j++) { - address = page_private(buffer->pages[j]); - dma_unmap_page(card->device, address, - PAGE_SIZE, DMA_TO_DEVICE); - __free_page(buffer->pages[j]); - } - kfree(buffer->pages); - out: - buffer->pages = NULL; - return retval; -} - -int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) -{ - unsigned long uaddr; - int i, retval; - - uaddr = vma->vm_start; - for (i = 0; i < buffer->page_count; i++) { - retval = vm_insert_page(vma, uaddr, buffer->pages[i]); - if (retval) - return retval; - uaddr += PAGE_SIZE; - } - - return 0; -} - -void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, - struct fw_card *card) -{ - int i; - dma_addr_t address; - - for (i = 0; i < buffer->page_count; i++) { - address = page_private(buffer->pages[i]); - dma_unmap_page(card->device, address, - PAGE_SIZE, DMA_TO_DEVICE); - __free_page(buffer->pages[i]); - } - - kfree(buffer->pages); - buffer->pages = NULL; -} - -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data) -{ - struct fw_iso_context *ctx; - - ctx = card->driver->allocate_iso_context(card, type, header_size); - if (IS_ERR(ctx)) - return ctx; - - ctx->card = card; - ctx->type = type; - ctx->channel = channel; - ctx->speed = speed; - ctx->header_size = header_size; - ctx->callback = callback; - ctx->callback_data = callback_data; - - return ctx; -} -EXPORT_SYMBOL(fw_iso_context_create); - -void fw_iso_context_destroy(struct fw_iso_context *ctx) -{ - struct fw_card *card = ctx->card; - - card->driver->free_iso_context(ctx); -} -EXPORT_SYMBOL(fw_iso_context_destroy); - -int -fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) -{ - return ctx->card->driver->start_iso(ctx, cycle, sync, tags); -} -EXPORT_SYMBOL(fw_iso_context_start); - -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct fw_card *card = ctx->card; - - return card->driver->queue_iso(ctx, packet, buffer, payload); -} -EXPORT_SYMBOL(fw_iso_context_queue); - -int -fw_iso_context_stop(struct fw_iso_context *ctx) -{ - return ctx->card->driver->stop_iso(ctx); -} -EXPORT_SYMBOL(fw_iso_context_stop); diff --git a/trunk/drivers/firewire/fw-ohci.c b/trunk/drivers/firewire/fw-ohci.c deleted file mode 100644 index 1f5c70461b8b..000000000000 --- a/trunk/drivers/firewire/fw-ohci.c +++ /dev/null @@ -1,1943 +0,0 @@ -/* - * Driver for OHCI 1394 controllers - * - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-ohci.h" - -#define DESCRIPTOR_OUTPUT_MORE 0 -#define DESCRIPTOR_OUTPUT_LAST (1 << 12) -#define DESCRIPTOR_INPUT_MORE (2 << 12) -#define DESCRIPTOR_INPUT_LAST (3 << 12) -#define DESCRIPTOR_STATUS (1 << 11) -#define DESCRIPTOR_KEY_IMMEDIATE (2 << 8) -#define DESCRIPTOR_PING (1 << 7) -#define DESCRIPTOR_YY (1 << 6) -#define DESCRIPTOR_NO_IRQ (0 << 4) -#define DESCRIPTOR_IRQ_ERROR (1 << 4) -#define DESCRIPTOR_IRQ_ALWAYS (3 << 4) -#define DESCRIPTOR_BRANCH_ALWAYS (3 << 2) -#define DESCRIPTOR_WAIT (3 << 0) - -struct descriptor { - __le16 req_count; - __le16 control; - __le32 data_address; - __le32 branch_address; - __le16 res_count; - __le16 transfer_status; -} __attribute__((aligned(16))); - -struct db_descriptor { - __le16 first_size; - __le16 control; - __le16 second_req_count; - __le16 first_req_count; - __le32 branch_address; - __le16 second_res_count; - __le16 first_res_count; - __le32 reserved0; - __le32 first_buffer; - __le32 second_buffer; - __le32 reserved1; -} __attribute__((aligned(16))); - -#define CONTROL_SET(regs) (regs) -#define CONTROL_CLEAR(regs) ((regs) + 4) -#define COMMAND_PTR(regs) ((regs) + 12) -#define CONTEXT_MATCH(regs) ((regs) + 16) - -struct ar_buffer { - struct descriptor descriptor; - struct ar_buffer *next; - __le32 data[0]; -}; - -struct ar_context { - struct fw_ohci *ohci; - struct ar_buffer *current_buffer; - struct ar_buffer *last_buffer; - void *pointer; - u32 regs; - struct tasklet_struct tasklet; -}; - -struct context; - -typedef int (*descriptor_callback_t)(struct context *ctx, - struct descriptor *d, - struct descriptor *last); -struct context { - struct fw_ohci *ohci; - u32 regs; - - struct descriptor *buffer; - dma_addr_t buffer_bus; - size_t buffer_size; - struct descriptor *head_descriptor; - struct descriptor *tail_descriptor; - struct descriptor *tail_descriptor_last; - struct descriptor *prev_descriptor; - - descriptor_callback_t callback; - - struct tasklet_struct tasklet; -}; - -#define IT_HEADER_SY(v) ((v) << 0) -#define IT_HEADER_TCODE(v) ((v) << 4) -#define IT_HEADER_CHANNEL(v) ((v) << 8) -#define IT_HEADER_TAG(v) ((v) << 14) -#define IT_HEADER_SPEED(v) ((v) << 16) -#define IT_HEADER_DATA_LENGTH(v) ((v) << 16) - -struct iso_context { - struct fw_iso_context base; - struct context context; - void *header; - size_t header_length; -}; - -#define CONFIG_ROM_SIZE 1024 - -struct fw_ohci { - struct fw_card card; - - u32 version; - __iomem char *registers; - dma_addr_t self_id_bus; - __le32 *self_id_cpu; - struct tasklet_struct bus_reset_tasklet; - int node_id; - int generation; - int request_generation; - u32 bus_seconds; - - /* - * Spinlock for accessing fw_ohci data. Never call out of - * this driver with this lock held. - */ - spinlock_t lock; - u32 self_id_buffer[512]; - - /* Config rom buffers */ - __be32 *config_rom; - dma_addr_t config_rom_bus; - __be32 *next_config_rom; - dma_addr_t next_config_rom_bus; - u32 next_header; - - struct ar_context ar_request_ctx; - struct ar_context ar_response_ctx; - struct context at_request_ctx; - struct context at_response_ctx; - - u32 it_context_mask; - struct iso_context *it_context_list; - u32 ir_context_mask; - struct iso_context *ir_context_list; -}; - -static inline struct fw_ohci *fw_ohci(struct fw_card *card) -{ - return container_of(card, struct fw_ohci, card); -} - -#define IT_CONTEXT_CYCLE_MATCH_ENABLE 0x80000000 -#define IR_CONTEXT_BUFFER_FILL 0x80000000 -#define IR_CONTEXT_ISOCH_HEADER 0x40000000 -#define IR_CONTEXT_CYCLE_MATCH_ENABLE 0x20000000 -#define IR_CONTEXT_MULTI_CHANNEL_MODE 0x10000000 -#define IR_CONTEXT_DUAL_BUFFER_MODE 0x08000000 - -#define CONTEXT_RUN 0x8000 -#define CONTEXT_WAKE 0x1000 -#define CONTEXT_DEAD 0x0800 -#define CONTEXT_ACTIVE 0x0400 - -#define OHCI1394_MAX_AT_REQ_RETRIES 0x2 -#define OHCI1394_MAX_AT_RESP_RETRIES 0x2 -#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 - -#define FW_OHCI_MAJOR 240 -#define OHCI1394_REGISTER_SIZE 0x800 -#define OHCI_LOOP_COUNT 500 -#define OHCI1394_PCI_HCI_Control 0x40 -#define SELF_ID_BUF_SIZE 0x800 -#define OHCI_TCODE_PHY_PACKET 0x0e -#define OHCI_VERSION_1_1 0x010010 -#define ISO_BUFFER_SIZE (64 * 1024) -#define AT_BUFFER_SIZE 4096 - -static char ohci_driver_name[] = KBUILD_MODNAME; - -static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) -{ - writel(data, ohci->registers + offset); -} - -static inline u32 reg_read(const struct fw_ohci *ohci, int offset) -{ - return readl(ohci->registers + offset); -} - -static inline void flush_writes(const struct fw_ohci *ohci) -{ - /* Do a dummy read to flush writes. */ - reg_read(ohci, OHCI1394_Version); -} - -static int -ohci_update_phy_reg(struct fw_card *card, int addr, - int clear_bits, int set_bits) -{ - struct fw_ohci *ohci = fw_ohci(card); - u32 val, old; - - reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); - msleep(2); - val = reg_read(ohci, OHCI1394_PhyControl); - if ((val & OHCI1394_PhyControl_ReadDone) == 0) { - fw_error("failed to set phy reg bits.\n"); - return -EBUSY; - } - - old = OHCI1394_PhyControl_ReadData(val); - old = (old & ~clear_bits) | set_bits; - reg_write(ohci, OHCI1394_PhyControl, - OHCI1394_PhyControl_Write(addr, old)); - - return 0; -} - -static int ar_context_add_page(struct ar_context *ctx) -{ - struct device *dev = ctx->ohci->card.device; - struct ar_buffer *ab; - dma_addr_t ab_bus; - size_t offset; - - ab = (struct ar_buffer *) __get_free_page(GFP_ATOMIC); - if (ab == NULL) - return -ENOMEM; - - ab_bus = dma_map_single(dev, ab, PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(ab_bus)) { - free_page((unsigned long) ab); - return -ENOMEM; - } - - memset(&ab->descriptor, 0, sizeof(ab->descriptor)); - ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | - DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS); - offset = offsetof(struct ar_buffer, data); - ab->descriptor.req_count = cpu_to_le16(PAGE_SIZE - offset); - ab->descriptor.data_address = cpu_to_le32(ab_bus + offset); - ab->descriptor.res_count = cpu_to_le16(PAGE_SIZE - offset); - ab->descriptor.branch_address = 0; - - dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); - - ctx->last_buffer->descriptor.branch_address = ab_bus | 1; - ctx->last_buffer->next = ab; - ctx->last_buffer = ab; - - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); - - return 0; -} - -static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) -{ - struct fw_ohci *ohci = ctx->ohci; - struct fw_packet p; - u32 status, length, tcode; - - p.header[0] = le32_to_cpu(buffer[0]); - p.header[1] = le32_to_cpu(buffer[1]); - p.header[2] = le32_to_cpu(buffer[2]); - - tcode = (p.header[0] >> 4) & 0x0f; - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_READ_QUADLET_RESPONSE: - p.header[3] = (__force __u32) buffer[3]; - p.header_length = 16; - p.payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST : - p.header[3] = le32_to_cpu(buffer[3]); - p.header_length = 16; - p.payload_length = 0; - break; - - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_READ_BLOCK_RESPONSE: - case TCODE_LOCK_REQUEST: - case TCODE_LOCK_RESPONSE: - p.header[3] = le32_to_cpu(buffer[3]); - p.header_length = 16; - p.payload_length = p.header[3] >> 16; - break; - - case TCODE_WRITE_RESPONSE: - case TCODE_READ_QUADLET_REQUEST: - case OHCI_TCODE_PHY_PACKET: - p.header_length = 12; - p.payload_length = 0; - break; - } - - p.payload = (void *) buffer + p.header_length; - - /* FIXME: What to do about evt_* errors? */ - length = (p.header_length + p.payload_length + 3) / 4; - status = le32_to_cpu(buffer[length]); - - p.ack = ((status >> 16) & 0x1f) - 16; - p.speed = (status >> 21) & 0x7; - p.timestamp = status & 0xffff; - p.generation = ohci->request_generation; - - /* - * The OHCI bus reset handler synthesizes a phy packet with - * the new generation number when a bus reset happens (see - * section 8.4.2.3). This helps us determine when a request - * was received and make sure we send the response in the same - * generation. We only need this for requests; for responses - * we use the unique tlabel for finding the matching - * request. - */ - - if (p.ack + 16 == 0x09) - ohci->request_generation = (buffer[2] >> 16) & 0xff; - else if (ctx == &ohci->ar_request_ctx) - fw_core_handle_request(&ohci->card, &p); - else - fw_core_handle_response(&ohci->card, &p); - - return buffer + length + 1; -} - -static void ar_context_tasklet(unsigned long data) -{ - struct ar_context *ctx = (struct ar_context *)data; - struct fw_ohci *ohci = ctx->ohci; - struct ar_buffer *ab; - struct descriptor *d; - void *buffer, *end; - - ab = ctx->current_buffer; - d = &ab->descriptor; - - if (d->res_count == 0) { - size_t size, rest, offset; - - /* - * This descriptor is finished and we may have a - * packet split across this and the next buffer. We - * reuse the page for reassembling the split packet. - */ - - offset = offsetof(struct ar_buffer, data); - dma_unmap_single(ohci->card.device, - ab->descriptor.data_address - offset, - PAGE_SIZE, DMA_BIDIRECTIONAL); - - buffer = ab; - ab = ab->next; - d = &ab->descriptor; - size = buffer + PAGE_SIZE - ctx->pointer; - rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); - memmove(buffer, ctx->pointer, size); - memcpy(buffer + size, ab->data, rest); - ctx->current_buffer = ab; - ctx->pointer = (void *) ab->data + rest; - end = buffer + size + rest; - - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); - - free_page((unsigned long)buffer); - ar_context_add_page(ctx); - } else { - buffer = ctx->pointer; - ctx->pointer = end = - (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count); - - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); - } -} - -static int -ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) -{ - struct ar_buffer ab; - - ctx->regs = regs; - ctx->ohci = ohci; - ctx->last_buffer = &ab; - tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx); - - ar_context_add_page(ctx); - ar_context_add_page(ctx); - ctx->current_buffer = ab.next; - ctx->pointer = ctx->current_buffer->data; - - reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab.descriptor.branch_address); - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); - - return 0; -} - -static void context_tasklet(unsigned long data) -{ - struct context *ctx = (struct context *) data; - struct fw_ohci *ohci = ctx->ohci; - struct descriptor *d, *last; - u32 address; - int z; - - dma_sync_single_for_cpu(ohci->card.device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - - d = ctx->tail_descriptor; - last = ctx->tail_descriptor_last; - - while (last->branch_address != 0) { - address = le32_to_cpu(last->branch_address); - z = address & 0xf; - d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d); - last = (z == 2) ? d : d + z - 1; - - if (!ctx->callback(ctx, d, last)) - break; - - ctx->tail_descriptor = d; - ctx->tail_descriptor_last = last; - } -} - -static int -context_init(struct context *ctx, struct fw_ohci *ohci, - size_t buffer_size, u32 regs, - descriptor_callback_t callback) -{ - ctx->ohci = ohci; - ctx->regs = regs; - ctx->buffer_size = buffer_size; - ctx->buffer = kmalloc(buffer_size, GFP_KERNEL); - if (ctx->buffer == NULL) - return -ENOMEM; - - tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx); - ctx->callback = callback; - - ctx->buffer_bus = - dma_map_single(ohci->card.device, ctx->buffer, - buffer_size, DMA_TO_DEVICE); - if (dma_mapping_error(ctx->buffer_bus)) { - kfree(ctx->buffer); - return -ENOMEM; - } - - ctx->head_descriptor = ctx->buffer; - ctx->prev_descriptor = ctx->buffer; - ctx->tail_descriptor = ctx->buffer; - ctx->tail_descriptor_last = ctx->buffer; - - /* - * We put a dummy descriptor in the buffer that has a NULL - * branch address and looks like it's been sent. That way we - * have a descriptor to append DMA programs to. Also, the - * ring buffer invariant is that it always has at least one - * element so that head == tail means buffer full. - */ - - memset(ctx->head_descriptor, 0, sizeof(*ctx->head_descriptor)); - ctx->head_descriptor->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST); - ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011); - ctx->head_descriptor++; - - return 0; -} - -static void -context_release(struct context *ctx) -{ - struct fw_card *card = &ctx->ohci->card; - - dma_unmap_single(card->device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - kfree(ctx->buffer); -} - -static struct descriptor * -context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) -{ - struct descriptor *d, *tail, *end; - - d = ctx->head_descriptor; - tail = ctx->tail_descriptor; - end = ctx->buffer + ctx->buffer_size / sizeof(*d); - - if (d + z <= tail) { - goto has_space; - } else if (d > tail && d + z <= end) { - goto has_space; - } else if (d > tail && ctx->buffer + z <= tail) { - d = ctx->buffer; - goto has_space; - } - - return NULL; - - has_space: - memset(d, 0, z * sizeof(*d)); - *d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d); - - return d; -} - -static void context_run(struct context *ctx, u32 extra) -{ - struct fw_ohci *ohci = ctx->ohci; - - reg_write(ohci, COMMAND_PTR(ctx->regs), - le32_to_cpu(ctx->tail_descriptor_last->branch_address)); - reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0); - reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra); - flush_writes(ohci); -} - -static void context_append(struct context *ctx, - struct descriptor *d, int z, int extra) -{ - dma_addr_t d_bus; - - d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d); - - ctx->head_descriptor = d + z + extra; - ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z); - ctx->prev_descriptor = z == 2 ? d : d + z - 1; - - dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); -} - -static void context_stop(struct context *ctx) -{ - u32 reg; - int i; - - reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); - - for (i = 0; i < 10; i++) { - reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); - if ((reg & CONTEXT_ACTIVE) == 0) - break; - - fw_notify("context_stop: still active (0x%08x)\n", reg); - msleep(1); - } -} - -struct driver_data { - struct fw_packet *packet; -}; - -/* - * This function apppends a packet to the DMA queue for transmission. - * Must always be called with the ochi->lock held to ensure proper - * generation handling and locking around packet queue manipulation. - */ -static int -at_context_queue_packet(struct context *ctx, struct fw_packet *packet) -{ - struct fw_ohci *ohci = ctx->ohci; - dma_addr_t d_bus, payload_bus; - struct driver_data *driver_data; - struct descriptor *d, *last; - __le32 *header; - int z, tcode; - u32 reg; - - d = context_get_descriptors(ctx, 4, &d_bus); - if (d == NULL) { - packet->ack = RCODE_SEND_ERROR; - return -1; - } - - d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); - d[0].res_count = cpu_to_le16(packet->timestamp); - - /* - * The DMA format for asyncronous link packets is different - * from the IEEE1394 layout, so shift the fields around - * accordingly. If header_length is 8, it's a PHY packet, to - * which we need to prepend an extra quadlet. - */ - - header = (__le32 *) &d[1]; - if (packet->header_length > 8) { - header[0] = cpu_to_le32((packet->header[0] & 0xffff) | - (packet->speed << 16)); - header[1] = cpu_to_le32((packet->header[1] & 0xffff) | - (packet->header[0] & 0xffff0000)); - header[2] = cpu_to_le32(packet->header[2]); - - tcode = (packet->header[0] >> 4) & 0x0f; - if (TCODE_IS_BLOCK_PACKET(tcode)) - header[3] = cpu_to_le32(packet->header[3]); - else - header[3] = (__force __le32) packet->header[3]; - - d[0].req_count = cpu_to_le16(packet->header_length); - } else { - header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | - (packet->speed << 16)); - header[1] = cpu_to_le32(packet->header[0]); - header[2] = cpu_to_le32(packet->header[1]); - d[0].req_count = cpu_to_le16(12); - } - - driver_data = (struct driver_data *) &d[3]; - driver_data->packet = packet; - packet->driver_data = driver_data; - - if (packet->payload_length > 0) { - payload_bus = - dma_map_single(ohci->card.device, packet->payload, - packet->payload_length, DMA_TO_DEVICE); - if (dma_mapping_error(payload_bus)) { - packet->ack = RCODE_SEND_ERROR; - return -1; - } - - d[2].req_count = cpu_to_le16(packet->payload_length); - d[2].data_address = cpu_to_le32(payload_bus); - last = &d[2]; - z = 3; - } else { - last = &d[0]; - z = 2; - } - - last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | - DESCRIPTOR_IRQ_ALWAYS | - DESCRIPTOR_BRANCH_ALWAYS); - - /* FIXME: Document how the locking works. */ - if (ohci->generation != packet->generation) { - packet->ack = RCODE_GENERATION; - return -1; - } - - context_append(ctx, d, z, 4 - z); - - /* If the context isn't already running, start it up. */ - reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); - if ((reg & CONTEXT_RUN) == 0) - context_run(ctx, 0); - - return 0; -} - -static int handle_at_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct driver_data *driver_data; - struct fw_packet *packet; - struct fw_ohci *ohci = context->ohci; - dma_addr_t payload_bus; - int evt; - - if (last->transfer_status == 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - driver_data = (struct driver_data *) &d[3]; - packet = driver_data->packet; - if (packet == NULL) - /* This packet was cancelled, just continue. */ - return 1; - - payload_bus = le32_to_cpu(last->data_address); - if (payload_bus != 0) - dma_unmap_single(ohci->card.device, payload_bus, - packet->payload_length, DMA_TO_DEVICE); - - evt = le16_to_cpu(last->transfer_status) & 0x1f; - packet->timestamp = le16_to_cpu(last->res_count); - - switch (evt) { - case OHCI1394_evt_timeout: - /* Async response transmit timed out. */ - packet->ack = RCODE_CANCELLED; - break; - - case OHCI1394_evt_flushed: - /* - * The packet was flushed should give same error as - * when we try to use a stale generation count. - */ - packet->ack = RCODE_GENERATION; - break; - - case OHCI1394_evt_missing_ack: - /* - * Using a valid (current) generation count, but the - * node is not on the bus or not sending acks. - */ - packet->ack = RCODE_NO_ACK; - break; - - case ACK_COMPLETE + 0x10: - case ACK_PENDING + 0x10: - case ACK_BUSY_X + 0x10: - case ACK_BUSY_A + 0x10: - case ACK_BUSY_B + 0x10: - case ACK_DATA_ERROR + 0x10: - case ACK_TYPE_ERROR + 0x10: - packet->ack = evt - 0x10; - break; - - default: - packet->ack = RCODE_SEND_ERROR; - break; - } - - packet->callback(packet, &ohci->card, packet->ack); - - return 1; -} - -#define HEADER_GET_DESTINATION(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_TCODE(q) (((q) >> 4) & 0x0f) -#define HEADER_GET_OFFSET_HIGH(q) (((q) >> 0) & 0xffff) -#define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - -static void -handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -{ - struct fw_packet response; - int tcode, length, i; - - tcode = HEADER_GET_TCODE(packet->header[0]); - if (TCODE_IS_BLOCK_PACKET(tcode)) - length = HEADER_GET_DATA_LENGTH(packet->header[3]); - else - length = 4; - - i = csr - CSR_CONFIG_ROM; - if (i + length > CONFIG_ROM_SIZE) { - fw_fill_response(&response, packet->header, - RCODE_ADDRESS_ERROR, NULL, 0); - } else if (!TCODE_IS_READ_REQUEST(tcode)) { - fw_fill_response(&response, packet->header, - RCODE_TYPE_ERROR, NULL, 0); - } else { - fw_fill_response(&response, packet->header, RCODE_COMPLETE, - (void *) ohci->config_rom + i, length); - } - - fw_core_handle_response(&ohci->card, &response); -} - -static void -handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -{ - struct fw_packet response; - int tcode, length, ext_tcode, sel; - __be32 *payload, lock_old; - u32 lock_arg, lock_data; - - tcode = HEADER_GET_TCODE(packet->header[0]); - length = HEADER_GET_DATA_LENGTH(packet->header[3]); - payload = packet->payload; - ext_tcode = HEADER_GET_EXTENDED_TCODE(packet->header[3]); - - if (tcode == TCODE_LOCK_REQUEST && - ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) { - lock_arg = be32_to_cpu(payload[0]); - lock_data = be32_to_cpu(payload[1]); - } else if (tcode == TCODE_READ_QUADLET_REQUEST) { - lock_arg = 0; - lock_data = 0; - } else { - fw_fill_response(&response, packet->header, - RCODE_TYPE_ERROR, NULL, 0); - goto out; - } - - sel = (csr - CSR_BUS_MANAGER_ID) / 4; - reg_write(ohci, OHCI1394_CSRData, lock_data); - reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); - reg_write(ohci, OHCI1394_CSRControl, sel); - - if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) - lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData)); - else - fw_notify("swap not done yet\n"); - - fw_fill_response(&response, packet->header, - RCODE_COMPLETE, &lock_old, sizeof(lock_old)); - out: - fw_core_handle_response(&ohci->card, &response); -} - -static void -handle_local_request(struct context *ctx, struct fw_packet *packet) -{ - u64 offset; - u32 csr; - - if (ctx == &ctx->ohci->at_request_ctx) { - packet->ack = ACK_PENDING; - packet->callback(packet, &ctx->ohci->card, packet->ack); - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(packet->header[1]) << 32) | - packet->header[2]; - csr = offset - CSR_REGISTER_BASE; - - /* Handle config rom reads. */ - if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END) - handle_local_rom(ctx->ohci, packet, csr); - else switch (csr) { - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: - handle_local_lock(ctx->ohci, packet, csr); - break; - default: - if (ctx == &ctx->ohci->at_request_ctx) - fw_core_handle_request(&ctx->ohci->card, packet); - else - fw_core_handle_response(&ctx->ohci->card, packet); - break; - } - - if (ctx == &ctx->ohci->at_response_ctx) { - packet->ack = ACK_COMPLETE; - packet->callback(packet, &ctx->ohci->card, packet->ack); - } -} - -static void -at_context_transmit(struct context *ctx, struct fw_packet *packet) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave(&ctx->ohci->lock, flags); - - if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id && - ctx->ohci->generation == packet->generation) { - spin_unlock_irqrestore(&ctx->ohci->lock, flags); - handle_local_request(ctx, packet); - return; - } - - retval = at_context_queue_packet(ctx, packet); - spin_unlock_irqrestore(&ctx->ohci->lock, flags); - - if (retval < 0) - packet->callback(packet, &ctx->ohci->card, packet->ack); - -} - -static void bus_reset_tasklet(unsigned long data) -{ - struct fw_ohci *ohci = (struct fw_ohci *)data; - int self_id_count, i, j, reg; - int generation, new_generation; - unsigned long flags; - - reg = reg_read(ohci, OHCI1394_NodeID); - if (!(reg & OHCI1394_NodeID_idValid)) { - fw_error("node ID not valid, new bus reset in progress\n"); - return; - } - ohci->node_id = reg & 0xffff; - - /* - * The count in the SelfIDCount register is the number of - * bytes in the self ID receive buffer. Since we also receive - * the inverted quadlets and a header quadlet, we shift one - * bit extra to get the actual number of self IDs. - */ - - self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; - generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; - - for (i = 1, j = 0; j < self_id_count; i += 2, j++) { - if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) - fw_error("inconsistent self IDs\n"); - ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]); - } - - /* - * Check the consistency of the self IDs we just read. The - * problem we face is that a new bus reset can start while we - * read out the self IDs from the DMA buffer. If this happens, - * the DMA buffer will be overwritten with new self IDs and we - * will read out inconsistent data. The OHCI specification - * (section 11.2) recommends a technique similar to - * linux/seqlock.h, where we remember the generation of the - * self IDs in the buffer before reading them out and compare - * it to the current generation after reading them out. If - * the two generations match we know we have a consistent set - * of self IDs. - */ - - new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; - if (new_generation != generation) { - fw_notify("recursive bus reset detected, " - "discarding self ids\n"); - return; - } - - /* FIXME: Document how the locking works. */ - spin_lock_irqsave(&ohci->lock, flags); - - ohci->generation = generation; - context_stop(&ohci->at_request_ctx); - context_stop(&ohci->at_response_ctx); - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - - /* - * This next bit is unrelated to the AT context stuff but we - * have to do it under the spinlock also. If a new config rom - * was set up before this reset, the old one is now no longer - * in use and we can free it. Update the config rom pointers - * to point to the current config rom and clear the - * next_config_rom pointer so a new udpate can take place. - */ - - if (ohci->next_config_rom != NULL) { - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); - ohci->config_rom = ohci->next_config_rom; - ohci->config_rom_bus = ohci->next_config_rom_bus; - ohci->next_config_rom = NULL; - - /* - * Restore config_rom image and manually update - * config_rom registers. Writing the header quadlet - * will indicate that the config rom is ready, so we - * do that last. - */ - reg_write(ohci, OHCI1394_BusOptions, - be32_to_cpu(ohci->config_rom[2])); - ohci->config_rom[0] = cpu_to_be32(ohci->next_header); - reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header); - } - - spin_unlock_irqrestore(&ohci->lock, flags); - - fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, - self_id_count, ohci->self_id_buffer); -} - -static irqreturn_t irq_handler(int irq, void *data) -{ - struct fw_ohci *ohci = data; - u32 event, iso_event, cycle_time; - int i; - - event = reg_read(ohci, OHCI1394_IntEventClear); - - if (!event) - return IRQ_NONE; - - reg_write(ohci, OHCI1394_IntEventClear, event); - - if (event & OHCI1394_selfIDComplete) - tasklet_schedule(&ohci->bus_reset_tasklet); - - if (event & OHCI1394_RQPkt) - tasklet_schedule(&ohci->ar_request_ctx.tasklet); - - if (event & OHCI1394_RSPkt) - tasklet_schedule(&ohci->ar_response_ctx.tasklet); - - if (event & OHCI1394_reqTxComplete) - tasklet_schedule(&ohci->at_request_ctx.tasklet); - - if (event & OHCI1394_respTxComplete) - tasklet_schedule(&ohci->at_response_ctx.tasklet); - - iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event); - - while (iso_event) { - i = ffs(iso_event) - 1; - tasklet_schedule(&ohci->ir_context_list[i].context.tasklet); - iso_event &= ~(1 << i); - } - - iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event); - - while (iso_event) { - i = ffs(iso_event) - 1; - tasklet_schedule(&ohci->it_context_list[i].context.tasklet); - iso_event &= ~(1 << i); - } - - if (event & OHCI1394_cycle64Seconds) { - cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - if ((cycle_time & 0x80000000) == 0) - ohci->bus_seconds++; - } - - return IRQ_HANDLED; -} - -static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct pci_dev *dev = to_pci_dev(card->device); - - /* - * When the link is not yet enabled, the atomic config rom - * update mechanism described below in ohci_set_config_rom() - * is not active. We have to update ConfigRomHeader and - * BusOptions manually, and the write to ConfigROMmap takes - * effect immediately. We tie this to the enabling of the - * link, so we have a valid config rom before enabling - the - * OHCI requires that ConfigROMhdr and BusOptions have valid - * values before enabling. - * - * However, when the ConfigROMmap is written, some controllers - * always read back quadlets 0 and 2 from the config rom to - * the ConfigRomHeader and BusOptions registers on bus reset. - * They shouldn't do that in this initial case where the link - * isn't enabled. This means we have to use the same - * workaround here, setting the bus header to 0 and then write - * the right values in the bus reset tasklet. - */ - - ohci->next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &ohci->next_config_rom_bus, GFP_KERNEL); - if (ohci->next_config_rom == NULL) - return -ENOMEM; - - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4); - - ohci->next_header = config_rom[0]; - ohci->next_config_rom[0] = 0; - reg_write(ohci, OHCI1394_ConfigROMhdr, 0); - reg_write(ohci, OHCI1394_BusOptions, config_rom[2]); - reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); - - reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); - - if (request_irq(dev->irq, irq_handler, - IRQF_SHARED, ohci_driver_name, ohci)) { - fw_error("Failed to allocate shared interrupt %d.\n", - dev->irq); - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); - return -EIO; - } - - reg_write(ohci, OHCI1394_HCControlSet, - OHCI1394_HCControl_linkEnable | - OHCI1394_HCControl_BIBimageValid); - flush_writes(ohci); - - /* - * We are ready to go, initiate bus reset to finish the - * initialization. - */ - - fw_core_initiate_bus_reset(&ohci->card, 1); - - return 0; -} - -static int -ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) -{ - struct fw_ohci *ohci; - unsigned long flags; - int retval = 0; - __be32 *next_config_rom; - dma_addr_t next_config_rom_bus; - - ohci = fw_ohci(card); - - /* - * When the OHCI controller is enabled, the config rom update - * mechanism is a bit tricky, but easy enough to use. See - * section 5.5.6 in the OHCI specification. - * - * The OHCI controller caches the new config rom address in a - * shadow register (ConfigROMmapNext) and needs a bus reset - * for the changes to take place. When the bus reset is - * detected, the controller loads the new values for the - * ConfigRomHeader and BusOptions registers from the specified - * config rom and loads ConfigROMmap from the ConfigROMmapNext - * shadow register. All automatically and atomically. - * - * Now, there's a twist to this story. The automatic load of - * ConfigRomHeader and BusOptions doesn't honor the - * noByteSwapData bit, so with a be32 config rom, the - * controller will load be32 values in to these registers - * during the atomic update, even on litte endian - * architectures. The workaround we use is to put a 0 in the - * header quadlet; 0 is endian agnostic and means that the - * config rom isn't ready yet. In the bus reset tasklet we - * then set up the real values for the two registers. - * - * We use ohci->lock to avoid racing with the code that sets - * ohci->next_config_rom to NULL (see bus_reset_tasklet). - */ - - next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &next_config_rom_bus, GFP_KERNEL); - if (next_config_rom == NULL) - return -ENOMEM; - - spin_lock_irqsave(&ohci->lock, flags); - - if (ohci->next_config_rom == NULL) { - ohci->next_config_rom = next_config_rom; - ohci->next_config_rom_bus = next_config_rom_bus; - - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, - length * 4); - - ohci->next_header = config_rom[0]; - ohci->next_config_rom[0] = 0; - - reg_write(ohci, OHCI1394_ConfigROMmap, - ohci->next_config_rom_bus); - } else { - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - next_config_rom, next_config_rom_bus); - retval = -EBUSY; - } - - spin_unlock_irqrestore(&ohci->lock, flags); - - /* - * Now initiate a bus reset to have the changes take - * effect. We clean up the old config rom memory and DMA - * mappings in the bus reset tasklet, since the OHCI - * controller could need to access it before the bus reset - * takes effect. - */ - if (retval == 0) - fw_core_initiate_bus_reset(&ohci->card, 1); - - return retval; -} - -static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - - at_context_transmit(&ohci->at_request_ctx, packet); -} - -static void ohci_send_response(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - - at_context_transmit(&ohci->at_response_ctx, packet); -} - -static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct context *ctx = &ohci->at_request_ctx; - struct driver_data *driver_data = packet->driver_data; - int retval = -ENOENT; - - tasklet_disable(&ctx->tasklet); - - if (packet->ack != 0) - goto out; - - driver_data->packet = NULL; - packet->ack = RCODE_CANCELLED; - packet->callback(packet, &ohci->card, packet->ack); - retval = 0; - - out: - tasklet_enable(&ctx->tasklet); - - return retval; -} - -static int -ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) -{ - struct fw_ohci *ohci = fw_ohci(card); - unsigned long flags; - int n, retval = 0; - - /* - * FIXME: Make sure this bitmask is cleared when we clear the busReset - * interrupt bit. Clear physReqResourceAllBuses on bus reset. - */ - - spin_lock_irqsave(&ohci->lock, flags); - - if (ohci->generation != generation) { - retval = -ESTALE; - goto out; - } - - /* - * Note, if the node ID contains a non-local bus ID, physical DMA is - * enabled for _all_ nodes on remote buses. - */ - - n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63; - if (n < 32) - reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << n); - else - reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32)); - - flush_writes(ohci); - out: - spin_unlock_irqrestore(&ohci->lock, flags); - return retval; -} - -static u64 -ohci_get_bus_time(struct fw_card *card) -{ - struct fw_ohci *ohci = fw_ohci(card); - u32 cycle_time; - u64 bus_time; - - cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time; - - return bus_time; -} - -static int handle_ir_dualbuffer_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct iso_context *ctx = - container_of(context, struct iso_context, context); - struct db_descriptor *db = (struct db_descriptor *) d; - __le32 *ir_header; - size_t header_length; - void *p, *end; - int i; - - if (db->first_res_count > 0 && db->second_res_count > 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - header_length = le16_to_cpu(db->first_req_count) - - le16_to_cpu(db->first_res_count); - - i = ctx->header_length; - p = db + 1; - end = p + header_length; - while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { - /* - * The iso header is byteswapped to little endian by - * the controller, but the remaining header quadlets - * are big endian. We want to present all the headers - * as big endian, so we have to swap the first - * quadlet. - */ - *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); - memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); - i += ctx->base.header_size; - p += ctx->base.header_size + 4; - } - - ctx->header_length = i; - - if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) { - ir_header = (__le32 *) (db + 1); - ctx->base.callback(&ctx->base, - le32_to_cpu(ir_header[0]) & 0xffff, - ctx->header_length, ctx->header, - ctx->base.callback_data); - ctx->header_length = 0; - } - - return 1; -} - -static int handle_it_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct iso_context *ctx = - container_of(context, struct iso_context, context); - - if (last->transfer_status == 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) - ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count), - 0, NULL, ctx->base.callback_data); - - return 1; -} - -static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct iso_context *ctx, *list; - descriptor_callback_t callback; - u32 *mask, regs; - unsigned long flags; - int index, retval = -ENOMEM; - - if (type == FW_ISO_CONTEXT_TRANSMIT) { - mask = &ohci->it_context_mask; - list = ohci->it_context_list; - callback = handle_it_packet; - } else { - mask = &ohci->ir_context_mask; - list = ohci->ir_context_list; - callback = handle_ir_dualbuffer_packet; - } - - /* FIXME: We need a fallback for pre 1.1 OHCI. */ - if (callback == handle_ir_dualbuffer_packet && - ohci->version < OHCI_VERSION_1_1) - return ERR_PTR(-EINVAL); - - spin_lock_irqsave(&ohci->lock, flags); - index = ffs(*mask) - 1; - if (index >= 0) - *mask &= ~(1 << index); - spin_unlock_irqrestore(&ohci->lock, flags); - - if (index < 0) - return ERR_PTR(-EBUSY); - - if (type == FW_ISO_CONTEXT_TRANSMIT) - regs = OHCI1394_IsoXmitContextBase(index); - else - regs = OHCI1394_IsoRcvContextBase(index); - - ctx = &list[index]; - memset(ctx, 0, sizeof(*ctx)); - ctx->header_length = 0; - ctx->header = (void *) __get_free_page(GFP_KERNEL); - if (ctx->header == NULL) - goto out; - - retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE, - regs, callback); - if (retval < 0) - goto out_with_header; - - return &ctx->base; - - out_with_header: - free_page((unsigned long)ctx->header); - out: - spin_lock_irqsave(&ohci->lock, flags); - *mask |= 1 << index; - spin_unlock_irqrestore(&ohci->lock, flags); - - return ERR_PTR(retval); -} - -static int ohci_start_iso(struct fw_iso_context *base, - s32 cycle, u32 sync, u32 tags) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct fw_ohci *ohci = ctx->context.ohci; - u32 control, match; - int index; - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - match = 0; - if (cycle >= 0) - match = IT_CONTEXT_CYCLE_MATCH_ENABLE | - (cycle & 0x7fff) << 16; - - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index); - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); - context_run(&ctx->context, match); - } else { - index = ctx - ohci->ir_context_list; - control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER; - match = (tags << 28) | (sync << 8) | ctx->base.channel; - if (cycle >= 0) { - match |= (cycle & 0x07fff) << 12; - control |= IR_CONTEXT_CYCLE_MATCH_ENABLE; - } - - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); - reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match); - context_run(&ctx->context, control); - } - - return 0; -} - -static int ohci_stop_iso(struct fw_iso_context *base) -{ - struct fw_ohci *ohci = fw_ohci(base->card); - struct iso_context *ctx = container_of(base, struct iso_context, base); - int index; - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); - } else { - index = ctx - ohci->ir_context_list; - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); - } - flush_writes(ohci); - context_stop(&ctx->context); - - return 0; -} - -static void ohci_free_iso_context(struct fw_iso_context *base) -{ - struct fw_ohci *ohci = fw_ohci(base->card); - struct iso_context *ctx = container_of(base, struct iso_context, base); - unsigned long flags; - int index; - - ohci_stop_iso(base); - context_release(&ctx->context); - free_page((unsigned long)ctx->header); - - spin_lock_irqsave(&ohci->lock, flags); - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - ohci->it_context_mask |= 1 << index; - } else { - index = ctx - ohci->ir_context_list; - ohci->ir_context_mask |= 1 << index; - } - - spin_unlock_irqrestore(&ohci->lock, flags); -} - -static int -ohci_queue_iso_transmit(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d, *last, *pd; - struct fw_iso_packet *p; - __le32 *header; - dma_addr_t d_bus, page_bus; - u32 z, header_z, payload_z, irq; - u32 payload_index, payload_end_index, next_page_index; - int page, end_page, i, length, offset; - - /* - * FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. - */ - - p = packet; - payload_index = payload; - - if (p->skip) - z = 1; - else - z = 2; - if (p->header_length > 0) - z++; - - /* Determine the first page the payload isn't contained in. */ - end_page = PAGE_ALIGN(payload_index + p->payload_length) >> PAGE_SHIFT; - if (p->payload_length > 0) - payload_z = end_page - (payload_index >> PAGE_SHIFT); - else - payload_z = 0; - - z += payload_z; - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(p->header_length, sizeof(*d)); - - d = context_get_descriptors(&ctx->context, z + header_z, &d_bus); - if (d == NULL) - return -ENOMEM; - - if (!p->skip) { - d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); - d[0].req_count = cpu_to_le16(8); - - header = (__le32 *) &d[1]; - header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) | - IT_HEADER_TAG(p->tag) | - IT_HEADER_TCODE(TCODE_STREAM_DATA) | - IT_HEADER_CHANNEL(ctx->base.channel) | - IT_HEADER_SPEED(ctx->base.speed)); - header[1] = - cpu_to_le32(IT_HEADER_DATA_LENGTH(p->header_length + - p->payload_length)); - } - - if (p->header_length > 0) { - d[2].req_count = cpu_to_le16(p->header_length); - d[2].data_address = cpu_to_le32(d_bus + z * sizeof(*d)); - memcpy(&d[z], p->header, p->header_length); - } - - pd = d + z - payload_z; - payload_end_index = payload_index + p->payload_length; - for (i = 0; i < payload_z; i++) { - page = payload_index >> PAGE_SHIFT; - offset = payload_index & ~PAGE_MASK; - next_page_index = (page + 1) << PAGE_SHIFT; - length = - min(next_page_index, payload_end_index) - payload_index; - pd[i].req_count = cpu_to_le16(length); - - page_bus = page_private(buffer->pages[page]); - pd[i].data_address = cpu_to_le32(page_bus + offset); - - payload_index += length; - } - - if (p->interrupt) - irq = DESCRIPTOR_IRQ_ALWAYS; - else - irq = DESCRIPTOR_NO_IRQ; - - last = z == 2 ? d : d + z - 1; - last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | - DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS | - irq); - - context_append(&ctx->context, d, z, header_z); - - return 0; -} - -static int -ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct db_descriptor *db = NULL; - struct descriptor *d; - struct fw_iso_packet *p; - dma_addr_t d_bus, page_bus; - u32 z, header_z, length, rest; - int page, offset, packet_count, header_size; - - /* - * FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. - */ - - if (packet->skip) { - d = context_get_descriptors(&ctx->context, 2, &d_bus); - if (d == NULL) - return -ENOMEM; - - db = (struct db_descriptor *) d; - db->control = cpu_to_le16(DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS | - DESCRIPTOR_WAIT); - db->first_size = cpu_to_le16(ctx->base.header_size + 4); - context_append(&ctx->context, d, 2, 0); - } - - p = packet; - z = 2; - - /* - * The OHCI controller puts the status word in the header - * buffer too, so we need 4 extra bytes per packet. - */ - packet_count = p->header_length / ctx->base.header_size; - header_size = packet_count * (ctx->base.header_size + 4); - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(header_size, sizeof(*d)); - page = payload >> PAGE_SHIFT; - offset = payload & ~PAGE_MASK; - rest = p->payload_length; - - /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ - /* FIXME: make packet-per-buffer/dual-buffer a context option */ - while (rest > 0) { - d = context_get_descriptors(&ctx->context, - z + header_z, &d_bus); - if (d == NULL) - return -ENOMEM; - - db = (struct db_descriptor *) d; - db->control = cpu_to_le16(DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS); - db->first_size = cpu_to_le16(ctx->base.header_size + 4); - db->first_req_count = cpu_to_le16(header_size); - db->first_res_count = db->first_req_count; - db->first_buffer = cpu_to_le32(d_bus + sizeof(*db)); - - if (offset + rest < PAGE_SIZE) - length = rest; - else - length = PAGE_SIZE - offset; - - db->second_req_count = cpu_to_le16(length); - db->second_res_count = db->second_req_count; - page_bus = page_private(buffer->pages[page]); - db->second_buffer = cpu_to_le32(page_bus + offset); - - if (p->interrupt && length == rest) - db->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); - - context_append(&ctx->context, d, z, header_z); - offset = (offset + length) & ~PAGE_MASK; - rest -= length; - page++; - } - - return 0; -} - -static int -ohci_queue_iso(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - - if (base->type == FW_ISO_CONTEXT_TRANSMIT) - return ohci_queue_iso_transmit(base, packet, buffer, payload); - else if (ctx->context.ohci->version >= OHCI_VERSION_1_1) - return ohci_queue_iso_receive_dualbuffer(base, packet, - buffer, payload); - else - /* FIXME: Implement fallback for OHCI 1.0 controllers. */ - return -EINVAL; -} - -static const struct fw_card_driver ohci_driver = { - .name = ohci_driver_name, - .enable = ohci_enable, - .update_phy_reg = ohci_update_phy_reg, - .set_config_rom = ohci_set_config_rom, - .send_request = ohci_send_request, - .send_response = ohci_send_response, - .cancel_packet = ohci_cancel_packet, - .enable_phys_dma = ohci_enable_phys_dma, - .get_bus_time = ohci_get_bus_time, - - .allocate_iso_context = ohci_allocate_iso_context, - .free_iso_context = ohci_free_iso_context, - .queue_iso = ohci_queue_iso, - .start_iso = ohci_start_iso, - .stop_iso = ohci_stop_iso, -}; - -static int software_reset(struct fw_ohci *ohci) -{ - int i; - - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if ((reg_read(ohci, OHCI1394_HCControlSet) & - OHCI1394_HCControl_softReset) == 0) - return 0; - msleep(1); - } - - return -EBUSY; -} - -static int __devinit -pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed; - u64 guid; - int err; - size_t size; - - ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); - if (ohci == NULL) { - fw_error("Could not malloc fw_ohci data.\n"); - return -ENOMEM; - } - - fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); - - err = pci_enable_device(dev); - if (err) { - fw_error("Failed to enable OHCI hardware.\n"); - goto fail_put_card; - } - - pci_set_master(dev); - pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); - pci_set_drvdata(dev, ohci); - - spin_lock_init(&ohci->lock); - - tasklet_init(&ohci->bus_reset_tasklet, - bus_reset_tasklet, (unsigned long)ohci); - - err = pci_request_region(dev, 0, ohci_driver_name); - if (err) { - fw_error("MMIO resource unavailable\n"); - goto fail_disable; - } - - ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE); - if (ohci->registers == NULL) { - fw_error("Failed to remap registers\n"); - err = -ENXIO; - goto fail_iomem; - } - - if (software_reset(ohci)) { - fw_error("Failed to reset ohci card.\n"); - err = -EBUSY; - goto fail_registers; - } - - /* - * Now enable LPS, which we need in order to start accessing - * most of the registers. In fact, on some cards (ALI M5251), - * accessing registers in the SClk domain without LPS enabled - * will lock up the machine. Wait 50msec to make sure we have - * full link enabled. - */ - reg_write(ohci, OHCI1394_HCControlSet, - OHCI1394_HCControl_LPS | - OHCI1394_HCControl_postedWriteEnable); - flush_writes(ohci); - msleep(50); - - reg_write(ohci, OHCI1394_HCControlClear, - OHCI1394_HCControl_noByteSwapData); - - reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_rcvSelfID | - OHCI1394_LinkControl_cycleTimerEnable | - OHCI1394_LinkControl_cycleMaster); - - ar_context_init(&ohci->ar_request_ctx, ohci, - OHCI1394_AsReqRcvContextControlSet); - - ar_context_init(&ohci->ar_response_ctx, ohci, - OHCI1394_AsRspRcvContextControlSet); - - context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE, - OHCI1394_AsReqTrContextControlSet, handle_at_packet); - - context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, - OHCI1394_AsRspTrContextControlSet, handle_at_packet); - - reg_write(ohci, OHCI1394_ATRetries, - OHCI1394_MAX_AT_REQ_RETRIES | - (OHCI1394_MAX_AT_RESP_RETRIES << 4) | - (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); - - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); - ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); - size = sizeof(struct iso_context) * hweight32(ohci->it_context_mask); - ohci->it_context_list = kzalloc(size, GFP_KERNEL); - - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); - ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); - size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); - ohci->ir_context_list = kzalloc(size, GFP_KERNEL); - - if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { - fw_error("Out of memory for it/ir contexts.\n"); - err = -ENOMEM; - goto fail_registers; - } - - /* self-id dma buffer allocation */ - ohci->self_id_cpu = dma_alloc_coherent(ohci->card.device, - SELF_ID_BUF_SIZE, - &ohci->self_id_bus, - GFP_KERNEL); - if (ohci->self_id_cpu == NULL) { - fw_error("Out of memory for self ID buffer.\n"); - err = -ENOMEM; - goto fail_registers; - } - - reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); - reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); - reg_write(ohci, OHCI1394_IntEventClear, ~0); - reg_write(ohci, OHCI1394_IntMaskClear, ~0); - reg_write(ohci, OHCI1394_IntMaskSet, - OHCI1394_selfIDComplete | - OHCI1394_RQPkt | OHCI1394_RSPkt | - OHCI1394_reqTxComplete | OHCI1394_respTxComplete | - OHCI1394_isochRx | OHCI1394_isochTx | - OHCI1394_masterIntEnable | - OHCI1394_cycle64Seconds); - - bus_options = reg_read(ohci, OHCI1394_BusOptions); - max_receive = (bus_options >> 12) & 0xf; - link_speed = bus_options & 0x7; - guid = ((u64) reg_read(ohci, OHCI1394_GUIDHi) << 32) | - reg_read(ohci, OHCI1394_GUIDLo); - - err = fw_card_add(&ohci->card, max_receive, link_speed, guid); - if (err < 0) - goto fail_self_id; - - ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; - fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", - dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); - - return 0; - - fail_self_id: - dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, - ohci->self_id_cpu, ohci->self_id_bus); - fail_registers: - kfree(ohci->it_context_list); - kfree(ohci->ir_context_list); - pci_iounmap(dev, ohci->registers); - fail_iomem: - pci_release_region(dev, 0); - fail_disable: - pci_disable_device(dev); - fail_put_card: - fw_card_put(&ohci->card); - - return err; -} - -static void pci_remove(struct pci_dev *dev) -{ - struct fw_ohci *ohci; - - ohci = pci_get_drvdata(dev); - reg_write(ohci, OHCI1394_IntMaskClear, ~0); - flush_writes(ohci); - fw_core_remove_card(&ohci->card); - - /* - * FIXME: Fail all pending packets here, now that the upper - * layers can't queue any more. - */ - - software_reset(ohci); - free_irq(dev->irq, ohci); - dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, - ohci->self_id_cpu, ohci->self_id_bus); - kfree(ohci->it_context_list); - kfree(ohci->ir_context_list); - pci_iounmap(dev, ohci->registers); - pci_release_region(dev, 0); - pci_disable_device(dev); - fw_card_put(&ohci->card); - - fw_notify("Removed fw-ohci device.\n"); -} - -static struct pci_device_id pci_table[] = { - { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, - { } -}; - -MODULE_DEVICE_TABLE(pci, pci_table); - -static struct pci_driver fw_ohci_pci_driver = { - .name = ohci_driver_name, - .id_table = pci_table, - .probe = pci_probe, - .remove = pci_remove, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers"); -MODULE_LICENSE("GPL"); - -/* Provide a module alias so root-on-sbp2 initrds don't break. */ -#ifndef CONFIG_IEEE1394_OHCI1394_MODULE -MODULE_ALIAS("ohci1394"); -#endif - -static int __init fw_ohci_init(void) -{ - return pci_register_driver(&fw_ohci_pci_driver); -} - -static void __exit fw_ohci_cleanup(void) -{ - pci_unregister_driver(&fw_ohci_pci_driver); -} - -module_init(fw_ohci_init); -module_exit(fw_ohci_cleanup); diff --git a/trunk/drivers/firewire/fw-ohci.h b/trunk/drivers/firewire/fw-ohci.h deleted file mode 100644 index fa15706397d7..000000000000 --- a/trunk/drivers/firewire/fw-ohci.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __fw_ohci_h -#define __fw_ohci_h - -/* OHCI register map */ - -#define OHCI1394_Version 0x000 -#define OHCI1394_GUID_ROM 0x004 -#define OHCI1394_ATRetries 0x008 -#define OHCI1394_CSRData 0x00C -#define OHCI1394_CSRCompareData 0x010 -#define OHCI1394_CSRControl 0x014 -#define OHCI1394_ConfigROMhdr 0x018 -#define OHCI1394_BusID 0x01C -#define OHCI1394_BusOptions 0x020 -#define OHCI1394_GUIDHi 0x024 -#define OHCI1394_GUIDLo 0x028 -#define OHCI1394_ConfigROMmap 0x034 -#define OHCI1394_PostedWriteAddressLo 0x038 -#define OHCI1394_PostedWriteAddressHi 0x03C -#define OHCI1394_VendorID 0x040 -#define OHCI1394_HCControlSet 0x050 -#define OHCI1394_HCControlClear 0x054 -#define OHCI1394_HCControl_BIBimageValid 0x80000000 -#define OHCI1394_HCControl_noByteSwapData 0x40000000 -#define OHCI1394_HCControl_programPhyEnable 0x00800000 -#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 -#define OHCI1394_HCControl_LPS 0x00080000 -#define OHCI1394_HCControl_postedWriteEnable 0x00040000 -#define OHCI1394_HCControl_linkEnable 0x00020000 -#define OHCI1394_HCControl_softReset 0x00010000 -#define OHCI1394_SelfIDBuffer 0x064 -#define OHCI1394_SelfIDCount 0x068 -#define OHCI1394_IRMultiChanMaskHiSet 0x070 -#define OHCI1394_IRMultiChanMaskHiClear 0x074 -#define OHCI1394_IRMultiChanMaskLoSet 0x078 -#define OHCI1394_IRMultiChanMaskLoClear 0x07C -#define OHCI1394_IntEventSet 0x080 -#define OHCI1394_IntEventClear 0x084 -#define OHCI1394_IntMaskSet 0x088 -#define OHCI1394_IntMaskClear 0x08C -#define OHCI1394_IsoXmitIntEventSet 0x090 -#define OHCI1394_IsoXmitIntEventClear 0x094 -#define OHCI1394_IsoXmitIntMaskSet 0x098 -#define OHCI1394_IsoXmitIntMaskClear 0x09C -#define OHCI1394_IsoRecvIntEventSet 0x0A0 -#define OHCI1394_IsoRecvIntEventClear 0x0A4 -#define OHCI1394_IsoRecvIntMaskSet 0x0A8 -#define OHCI1394_IsoRecvIntMaskClear 0x0AC -#define OHCI1394_InitialBandwidthAvailable 0x0B0 -#define OHCI1394_InitialChannelsAvailableHi 0x0B4 -#define OHCI1394_InitialChannelsAvailableLo 0x0B8 -#define OHCI1394_FairnessControl 0x0DC -#define OHCI1394_LinkControlSet 0x0E0 -#define OHCI1394_LinkControlClear 0x0E4 -#define OHCI1394_LinkControl_rcvSelfID (1 << 9) -#define OHCI1394_LinkControl_rcvPhyPkt (1 << 10) -#define OHCI1394_LinkControl_cycleTimerEnable (1 << 20) -#define OHCI1394_LinkControl_cycleMaster (1 << 21) -#define OHCI1394_LinkControl_cycleSource (1 << 22) -#define OHCI1394_NodeID 0x0E8 -#define OHCI1394_NodeID_idValid 0x80000000 -#define OHCI1394_PhyControl 0x0EC -#define OHCI1394_PhyControl_Read(addr) (((addr) << 8) | 0x00008000) -#define OHCI1394_PhyControl_ReadDone 0x80000000 -#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) -#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) -#define OHCI1394_PhyControl_WriteDone 0x00004000 -#define OHCI1394_IsochronousCycleTimer 0x0F0 -#define OHCI1394_AsReqFilterHiSet 0x100 -#define OHCI1394_AsReqFilterHiClear 0x104 -#define OHCI1394_AsReqFilterLoSet 0x108 -#define OHCI1394_AsReqFilterLoClear 0x10C -#define OHCI1394_PhyReqFilterHiSet 0x110 -#define OHCI1394_PhyReqFilterHiClear 0x114 -#define OHCI1394_PhyReqFilterLoSet 0x118 -#define OHCI1394_PhyReqFilterLoClear 0x11C -#define OHCI1394_PhyUpperBound 0x120 - -#define OHCI1394_AsReqTrContextBase 0x180 -#define OHCI1394_AsReqTrContextControlSet 0x180 -#define OHCI1394_AsReqTrContextControlClear 0x184 -#define OHCI1394_AsReqTrCommandPtr 0x18C - -#define OHCI1394_AsRspTrContextBase 0x1A0 -#define OHCI1394_AsRspTrContextControlSet 0x1A0 -#define OHCI1394_AsRspTrContextControlClear 0x1A4 -#define OHCI1394_AsRspTrCommandPtr 0x1AC - -#define OHCI1394_AsReqRcvContextBase 0x1C0 -#define OHCI1394_AsReqRcvContextControlSet 0x1C0 -#define OHCI1394_AsReqRcvContextControlClear 0x1C4 -#define OHCI1394_AsReqRcvCommandPtr 0x1CC - -#define OHCI1394_AsRspRcvContextBase 0x1E0 -#define OHCI1394_AsRspRcvContextControlSet 0x1E0 -#define OHCI1394_AsRspRcvContextControlClear 0x1E4 -#define OHCI1394_AsRspRcvCommandPtr 0x1EC - -/* Isochronous transmit registers */ -#define OHCI1394_IsoXmitContextBase(n) (0x200 + 16 * (n)) -#define OHCI1394_IsoXmitContextControlSet(n) (0x200 + 16 * (n)) -#define OHCI1394_IsoXmitContextControlClear(n) (0x204 + 16 * (n)) -#define OHCI1394_IsoXmitCommandPtr(n) (0x20C + 16 * (n)) - -/* Isochronous receive registers */ -#define OHCI1394_IsoRcvContextBase(n) (0x400 + 32 * (n)) -#define OHCI1394_IsoRcvContextControlSet(n) (0x400 + 32 * (n)) -#define OHCI1394_IsoRcvContextControlClear(n) (0x404 + 32 * (n)) -#define OHCI1394_IsoRcvCommandPtr(n) (0x40C + 32 * (n)) -#define OHCI1394_IsoRcvContextMatch(n) (0x410 + 32 * (n)) - -/* Interrupts Mask/Events */ -#define OHCI1394_reqTxComplete 0x00000001 -#define OHCI1394_respTxComplete 0x00000002 -#define OHCI1394_ARRQ 0x00000004 -#define OHCI1394_ARRS 0x00000008 -#define OHCI1394_RQPkt 0x00000010 -#define OHCI1394_RSPkt 0x00000020 -#define OHCI1394_isochTx 0x00000040 -#define OHCI1394_isochRx 0x00000080 -#define OHCI1394_postedWriteErr 0x00000100 -#define OHCI1394_lockRespErr 0x00000200 -#define OHCI1394_selfIDComplete 0x00010000 -#define OHCI1394_busReset 0x00020000 -#define OHCI1394_phy 0x00080000 -#define OHCI1394_cycleSynch 0x00100000 -#define OHCI1394_cycle64Seconds 0x00200000 -#define OHCI1394_cycleLost 0x00400000 -#define OHCI1394_cycleInconsistent 0x00800000 -#define OHCI1394_unrecoverableError 0x01000000 -#define OHCI1394_cycleTooLong 0x02000000 -#define OHCI1394_phyRegRcvd 0x04000000 -#define OHCI1394_masterIntEnable 0x80000000 - -#define OHCI1394_evt_no_status 0x0 -#define OHCI1394_evt_long_packet 0x2 -#define OHCI1394_evt_missing_ack 0x3 -#define OHCI1394_evt_underrun 0x4 -#define OHCI1394_evt_overrun 0x5 -#define OHCI1394_evt_descriptor_read 0x6 -#define OHCI1394_evt_data_read 0x7 -#define OHCI1394_evt_data_write 0x8 -#define OHCI1394_evt_bus_reset 0x9 -#define OHCI1394_evt_timeout 0xa -#define OHCI1394_evt_tcode_err 0xb -#define OHCI1394_evt_reserved_b 0xc -#define OHCI1394_evt_reserved_c 0xd -#define OHCI1394_evt_unknown 0xe -#define OHCI1394_evt_flushed 0xf - -#define OHCI1394_phy_tcode 0xe - -#endif /* __fw_ohci_h */ diff --git a/trunk/drivers/firewire/fw-sbp2.c b/trunk/drivers/firewire/fw-sbp2.c deleted file mode 100644 index 68300414e5f4..000000000000 --- a/trunk/drivers/firewire/fw-sbp2.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * SBP2 driver (SCSI over IEEE1394) - * - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The basic structure of this driver is based on the old storage driver, - * drivers/ieee1394/sbp2.c, originally written by - * James Goodwin - * with later contributions and ongoing maintenance from - * Ben Collins , - * Stefan Richter - * and many others. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -/* I don't know why the SCSI stack doesn't define something like this... */ -typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); - -static const char sbp2_driver_name[] = "sbp2"; - -struct sbp2_device { - struct kref kref; - struct fw_unit *unit; - struct fw_address_handler address_handler; - struct list_head orb_list; - u64 management_agent_address; - u64 command_block_agent_address; - u32 workarounds; - int login_id; - - /* - * We cache these addresses and only update them once we've - * logged in or reconnected to the sbp2 device. That way, any - * IO to the device will automatically fail and get retried if - * it happens in a window where the device is not ready to - * handle it (e.g. after a bus reset but before we reconnect). - */ - int node_id; - int address_high; - int generation; - - int retries; - struct delayed_work work; -}; - -#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2_MAX_SECTORS 255 /* Max sectors supported */ -#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */ - -#define SBP2_ORB_NULL 0x80000000 - -#define SBP2_DIRECTION_TO_MEDIA 0x0 -#define SBP2_DIRECTION_FROM_MEDIA 0x1 - -/* Unit directory keys */ -#define SBP2_COMMAND_SET_SPECIFIER 0x38 -#define SBP2_COMMAND_SET 0x39 -#define SBP2_COMMAND_SET_REVISION 0x3b -#define SBP2_FIRMWARE_REVISION 0x3c - -/* Flags for detected oddities and brokeness */ -#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 -#define SBP2_WORKAROUND_INQUIRY_36 0x2 -#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 -#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_OVERRIDE 0x100 - -/* Management orb opcodes */ -#define SBP2_LOGIN_REQUEST 0x0 -#define SBP2_QUERY_LOGINS_REQUEST 0x1 -#define SBP2_RECONNECT_REQUEST 0x3 -#define SBP2_SET_PASSWORD_REQUEST 0x4 -#define SBP2_LOGOUT_REQUEST 0x7 -#define SBP2_ABORT_TASK_REQUEST 0xb -#define SBP2_ABORT_TASK_SET 0xc -#define SBP2_LOGICAL_UNIT_RESET 0xe -#define SBP2_TARGET_RESET_REQUEST 0xf - -/* Offsets for command block agent registers */ -#define SBP2_AGENT_STATE 0x00 -#define SBP2_AGENT_RESET 0x04 -#define SBP2_ORB_POINTER 0x08 -#define SBP2_DOORBELL 0x10 -#define SBP2_UNSOLICITED_STATUS_ENABLE 0x14 - -/* Status write response codes */ -#define SBP2_STATUS_REQUEST_COMPLETE 0x0 -#define SBP2_STATUS_TRANSPORT_FAILURE 0x1 -#define SBP2_STATUS_ILLEGAL_REQUEST 0x2 -#define SBP2_STATUS_VENDOR_DEPENDENT 0x3 - -#define STATUS_GET_ORB_HIGH(v) ((v).status & 0xffff) -#define STATUS_GET_SBP_STATUS(v) (((v).status >> 16) & 0xff) -#define STATUS_GET_LEN(v) (((v).status >> 24) & 0x07) -#define STATUS_GET_DEAD(v) (((v).status >> 27) & 0x01) -#define STATUS_GET_RESPONSE(v) (((v).status >> 28) & 0x03) -#define STATUS_GET_SOURCE(v) (((v).status >> 30) & 0x03) -#define STATUS_GET_ORB_LOW(v) ((v).orb_low) -#define STATUS_GET_DATA(v) ((v).data) - -struct sbp2_status { - u32 status; - u32 orb_low; - u8 data[24]; -}; - -struct sbp2_pointer { - u32 high; - u32 low; -}; - -struct sbp2_orb { - struct fw_transaction t; - dma_addr_t request_bus; - int rcode; - struct sbp2_pointer pointer; - void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status); - struct list_head link; -}; - -#define MANAGEMENT_ORB_LUN(v) ((v)) -#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16) -#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20) -#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28) -#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29) -#define MANAGEMENT_ORB_NOTIFY ((1) << 31) - -#define MANAGEMENT_ORB_RESPONSE_LENGTH(v) ((v)) -#define MANAGEMENT_ORB_PASSWORD_LENGTH(v) ((v) << 16) - -struct sbp2_management_orb { - struct sbp2_orb base; - struct { - struct sbp2_pointer password; - struct sbp2_pointer response; - u32 misc; - u32 length; - struct sbp2_pointer status_fifo; - } request; - __be32 response[4]; - dma_addr_t response_bus; - struct completion done; - struct sbp2_status status; -}; - -#define LOGIN_RESPONSE_GET_LOGIN_ID(v) ((v).misc & 0xffff) -#define LOGIN_RESPONSE_GET_LENGTH(v) (((v).misc >> 16) & 0xffff) - -struct sbp2_login_response { - u32 misc; - struct sbp2_pointer command_block_agent; - u32 reconnect_hold; -}; -#define COMMAND_ORB_DATA_SIZE(v) ((v)) -#define COMMAND_ORB_PAGE_SIZE(v) ((v) << 16) -#define COMMAND_ORB_PAGE_TABLE_PRESENT ((1) << 19) -#define COMMAND_ORB_MAX_PAYLOAD(v) ((v) << 20) -#define COMMAND_ORB_SPEED(v) ((v) << 24) -#define COMMAND_ORB_DIRECTION(v) ((v) << 27) -#define COMMAND_ORB_REQUEST_FORMAT(v) ((v) << 29) -#define COMMAND_ORB_NOTIFY ((1) << 31) - -struct sbp2_command_orb { - struct sbp2_orb base; - struct { - struct sbp2_pointer next; - struct sbp2_pointer data_descriptor; - u32 misc; - u8 command_block[12]; - } request; - struct scsi_cmnd *cmd; - scsi_done_fn_t done; - struct fw_unit *unit; - - struct sbp2_pointer page_table[SG_ALL]; - dma_addr_t page_table_bus; - dma_addr_t request_buffer_bus; -}; - -/* - * List of devices with known bugs. - * - * The firmware_revision field, masked with 0xffff00, is the best - * indicator for the type of bridge chip of a device. It yields a few - * false positives but this did not break correctly behaving devices - * so far. We use ~0 as a wildcard, since the 24 bit values we get - * from the config rom can never match that. - */ -static const struct { - u32 firmware_revision; - u32 model; - unsigned workarounds; -} sbp2_workarounds_table[] = { - /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { - .firmware_revision = 0x002800, - .model = 0x001010, - .workarounds = SBP2_WORKAROUND_INQUIRY_36 | - SBP2_WORKAROUND_MODE_SENSE_8, - }, - /* Initio bridges, actually only needed for some older ones */ { - .firmware_revision = 0x000200, - .model = ~0, - .workarounds = SBP2_WORKAROUND_INQUIRY_36, - }, - /* Symbios bridge */ { - .firmware_revision = 0xa0b800, - .model = ~0, - .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, - }, - - /* - * There are iPods (2nd gen, 3rd gen) with model_id == 0, but - * these iPods do not feature the read_capacity bug according - * to one report. Read_capacity behaviour as well as model_id - * could change due to Apple-supplied firmware updates though. - */ - - /* iPod 4th generation. */ { - .firmware_revision = 0x0a2700, - .model = 0x000021, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod mini */ { - .firmware_revision = 0x0a2700, - .model = 0x000023, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod Photo */ { - .firmware_revision = 0x0a2700, - .model = 0x00007e, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - } -}; - -static void -sbp2_status_write(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - struct sbp2_device *sd = callback_data; - struct sbp2_orb *orb; - struct sbp2_status status; - size_t header_size; - unsigned long flags; - - if (tcode != TCODE_WRITE_BLOCK_REQUEST || - length == 0 || length > sizeof(status)) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - return; - } - - header_size = min(length, 2 * sizeof(u32)); - fw_memcpy_from_be32(&status, payload, header_size); - if (length > header_size) - memcpy(status.data, payload + 8, length - header_size); - if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { - fw_notify("non-orb related status write, not handled\n"); - fw_send_response(card, request, RCODE_COMPLETE); - return; - } - - /* Lookup the orb corresponding to this status write. */ - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(orb, &sd->orb_list, link) { - if (STATUS_GET_ORB_HIGH(status) == 0 && - STATUS_GET_ORB_LOW(status) == orb->request_bus && - orb->rcode == RCODE_COMPLETE) { - list_del(&orb->link); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&orb->link != &sd->orb_list) - orb->callback(orb, &status); - else - fw_error("status write for unknown orb\n"); - - fw_send_response(card, request, RCODE_COMPLETE); -} - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct sbp2_orb *orb = data; - unsigned long flags; - - orb->rcode = rcode; - if (rcode != RCODE_COMPLETE) { - spin_lock_irqsave(&card->lock, flags); - list_del(&orb->link); - spin_unlock_irqrestore(&card->lock, flags); - orb->callback(orb, NULL); - } -} - -static void -sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, - int node_id, int generation, u64 offset) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - unsigned long flags; - - orb->pointer.high = 0; - orb->pointer.low = orb->request_bus; - fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); - - spin_lock_irqsave(&device->card->lock, flags); - list_add_tail(&orb->link, &sd->orb_list); - spin_unlock_irqrestore(&device->card->lock, flags); - - fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, - node_id, generation, - device->node->max_speed, offset, - &orb->pointer, sizeof(orb->pointer), - complete_transaction, orb); -} - -static int sbp2_cancel_orbs(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct sbp2_orb *orb, *next; - struct list_head list; - unsigned long flags; - int retval = -ENOENT; - - INIT_LIST_HEAD(&list); - spin_lock_irqsave(&device->card->lock, flags); - list_splice_init(&sd->orb_list, &list); - spin_unlock_irqrestore(&device->card->lock, flags); - - list_for_each_entry_safe(orb, next, &list, link) { - retval = 0; - if (fw_cancel_transaction(device->card, &orb->t) == 0) - continue; - - orb->rcode = RCODE_CANCELLED; - orb->callback(orb, NULL); - } - - return retval; -} - -static void -complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -{ - struct sbp2_management_orb *orb = - (struct sbp2_management_orb *)base_orb; - - if (status) - memcpy(&orb->status, status, sizeof(*status)); - complete(&orb->done); -} - -static int -sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, - int function, int lun, void *response) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct sbp2_management_orb *orb; - int retval = -ENOMEM; - - orb = kzalloc(sizeof(*orb), GFP_ATOMIC); - if (orb == NULL) - return -ENOMEM; - - /* - * The sbp2 device is going to send a block read request to - * read out the request from host memory, so map it for dma. - */ - orb->base.request_bus = - dma_map_single(device->card->device, &orb->request, - sizeof(orb->request), DMA_TO_DEVICE); - if (dma_mapping_error(orb->base.request_bus)) - goto out; - - orb->response_bus = - dma_map_single(device->card->device, &orb->response, - sizeof(orb->response), DMA_FROM_DEVICE); - if (dma_mapping_error(orb->response_bus)) - goto out; - - orb->request.response.high = 0; - orb->request.response.low = orb->response_bus; - - orb->request.misc = - MANAGEMENT_ORB_NOTIFY | - MANAGEMENT_ORB_FUNCTION(function) | - MANAGEMENT_ORB_LUN(lun); - orb->request.length = - MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); - - orb->request.status_fifo.high = sd->address_handler.offset >> 32; - orb->request.status_fifo.low = sd->address_handler.offset; - - /* - * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive - * login and 1 second reconnect time. The reconnect setting - * is probably fine, but the exclusive login should be an option. - */ - if (function == SBP2_LOGIN_REQUEST) { - orb->request.misc |= - MANAGEMENT_ORB_EXCLUSIVE | - MANAGEMENT_ORB_RECONNECT(0); - } - - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); - - init_completion(&orb->done); - orb->base.callback = complete_management_orb; - - sbp2_send_orb(&orb->base, unit, - node_id, generation, sd->management_agent_address); - - wait_for_completion_timeout(&orb->done, - msecs_to_jiffies(SBP2_ORB_TIMEOUT)); - - retval = -EIO; - if (sbp2_cancel_orbs(unit) == 0) { - fw_error("orb reply timed out, rcode=0x%02x\n", - orb->base.rcode); - goto out; - } - - if (orb->base.rcode != RCODE_COMPLETE) { - fw_error("management write failed, rcode 0x%02x\n", - orb->base.rcode); - goto out; - } - - if (STATUS_GET_RESPONSE(orb->status) != 0 || - STATUS_GET_SBP_STATUS(orb->status) != 0) { - fw_error("error status: %d:%d\n", - STATUS_GET_RESPONSE(orb->status), - STATUS_GET_SBP_STATUS(orb->status)); - goto out; - } - - retval = 0; - out: - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - dma_unmap_single(device->card->device, orb->response_bus, - sizeof(orb->response), DMA_FROM_DEVICE); - - if (response) - fw_memcpy_from_be32(response, - orb->response, sizeof(orb->response)); - kfree(orb); - - return retval; -} - -static void -complete_agent_reset_write(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct fw_transaction *t = data; - - kfree(t); -} - -static int sbp2_agent_reset(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct fw_transaction *t; - static u32 zero; - - t = kzalloc(sizeof(*t), GFP_ATOMIC); - if (t == NULL) - return -ENOMEM; - - fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, - sd->node_id, sd->generation, SCODE_400, - sd->command_block_agent_address + SBP2_AGENT_RESET, - &zero, sizeof(zero), complete_agent_reset_write, t); - - return 0; -} - -static void sbp2_reconnect(struct work_struct *work); -static struct scsi_host_template scsi_driver_template; - -static void -release_sbp2_device(struct kref *kref) -{ - struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); - struct Scsi_Host *host = - container_of((void *)sd, struct Scsi_Host, hostdata[0]); - - sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, - SBP2_LOGOUT_REQUEST, sd->login_id, NULL); - - scsi_remove_host(host); - fw_core_remove_address_handler(&sd->address_handler); - fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); - put_device(&sd->unit->device); - scsi_host_put(host); -} - -static void sbp2_login(struct work_struct *work) -{ - struct sbp2_device *sd = - container_of(work, struct sbp2_device, work.work); - struct Scsi_Host *host = - container_of((void *)sd, struct Scsi_Host, hostdata[0]); - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_login_response response; - int generation, node_id, local_node_id, lun, retval; - - /* FIXME: Make this work for multi-lun devices. */ - lun = 0; - - generation = device->card->generation; - node_id = device->node->node_id; - local_node_id = device->card->local_node->node_id; - - if (sbp2_send_management_orb(unit, node_id, generation, - SBP2_LOGIN_REQUEST, lun, &response) < 0) { - if (sd->retries++ < 5) { - schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); - } else { - fw_error("failed to login to %s\n", - unit->device.bus_id); - kref_put(&sd->kref, release_sbp2_device); - } - return; - } - - sd->generation = generation; - sd->node_id = node_id; - sd->address_high = local_node_id << 16; - - /* Get command block agent offset and login id. */ - sd->command_block_agent_address = - ((u64) (response.command_block_agent.high & 0xffff) << 32) | - response.command_block_agent.low; - sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); - - fw_notify("logged in to sbp2 unit %s (%d retries)\n", - unit->device.bus_id, sd->retries); - fw_notify(" - management_agent_address: 0x%012llx\n", - (unsigned long long) sd->management_agent_address); - fw_notify(" - command_block_agent_address: 0x%012llx\n", - (unsigned long long) sd->command_block_agent_address); - fw_notify(" - status write address: 0x%012llx\n", - (unsigned long long) sd->address_handler.offset); - -#if 0 - /* FIXME: The linux1394 sbp2 does this last step. */ - sbp2_set_busy_timeout(scsi_id); -#endif - - PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect); - sbp2_agent_reset(unit); - - /* FIXME: Loop over luns here. */ - lun = 0; - retval = scsi_add_device(host, 0, 0, lun); - if (retval < 0) { - sbp2_send_management_orb(unit, sd->node_id, sd->generation, - SBP2_LOGOUT_REQUEST, sd->login_id, - NULL); - /* - * Set this back to sbp2_login so we fall back and - * retry login on bus reset. - */ - PREPARE_DELAYED_WORK(&sd->work, sbp2_login); - } - kref_put(&sd->kref, release_sbp2_device); -} - -static int sbp2_probe(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd; - struct fw_csr_iterator ci; - struct Scsi_Host *host; - int i, key, value, err; - u32 model, firmware_revision; - - err = -ENOMEM; - host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd)); - if (host == NULL) - goto fail; - - sd = (struct sbp2_device *) host->hostdata; - unit->device.driver_data = sd; - sd->unit = unit; - INIT_LIST_HEAD(&sd->orb_list); - kref_init(&sd->kref); - - sd->address_handler.length = 0x100; - sd->address_handler.address_callback = sbp2_status_write; - sd->address_handler.callback_data = sd; - - err = fw_core_add_address_handler(&sd->address_handler, - &fw_high_memory_region); - if (err < 0) - goto fail_host; - - err = fw_device_enable_phys_dma(device); - if (err < 0) - goto fail_address_handler; - - err = scsi_add_host(host, &unit->device); - if (err < 0) - goto fail_address_handler; - - /* - * Scan unit directory to get management agent address, - * firmware revison and model. Initialize firmware_revision - * and model to values that wont match anything in our table. - */ - firmware_revision = 0xff000000; - model = 0xff000000; - fw_csr_iterator_init(&ci, unit->directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_DEPENDENT_INFO | CSR_OFFSET: - sd->management_agent_address = - 0xfffff0000000ULL + 4 * value; - break; - case SBP2_FIRMWARE_REVISION: - firmware_revision = value; - break; - case CSR_MODEL: - model = value; - break; - } - } - - for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { - if (sbp2_workarounds_table[i].firmware_revision != - (firmware_revision & 0xffffff00)) - continue; - if (sbp2_workarounds_table[i].model != model && - sbp2_workarounds_table[i].model != ~0) - continue; - sd->workarounds |= sbp2_workarounds_table[i].workarounds; - break; - } - - if (sd->workarounds) - fw_notify("Workarounds for node %s: 0x%x " - "(firmware_revision 0x%06x, model_id 0x%06x)\n", - unit->device.bus_id, - sd->workarounds, firmware_revision, model); - - get_device(&unit->device); - - /* - * We schedule work to do the login so we can easily - * reschedule retries. Always get the ref before scheduling - * work. - */ - INIT_DELAYED_WORK(&sd->work, sbp2_login); - if (schedule_delayed_work(&sd->work, 0)) - kref_get(&sd->kref); - - return 0; - - fail_address_handler: - fw_core_remove_address_handler(&sd->address_handler); - fail_host: - scsi_host_put(host); - fail: - return err; -} - -static int sbp2_remove(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct sbp2_device *sd = unit->device.driver_data; - - kref_put(&sd->kref, release_sbp2_device); - - return 0; -} - -static void sbp2_reconnect(struct work_struct *work) -{ - struct sbp2_device *sd = - container_of(work, struct sbp2_device, work.work); - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - int generation, node_id, local_node_id; - - generation = device->card->generation; - node_id = device->node->node_id; - local_node_id = device->card->local_node->node_id; - - if (sbp2_send_management_orb(unit, node_id, generation, - SBP2_RECONNECT_REQUEST, - sd->login_id, NULL) < 0) { - if (sd->retries++ >= 5) { - fw_error("failed to reconnect to %s\n", - unit->device.bus_id); - /* Fall back and try to log in again. */ - sd->retries = 0; - PREPARE_DELAYED_WORK(&sd->work, sbp2_login); - } - schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); - return; - } - - sd->generation = generation; - sd->node_id = node_id; - sd->address_high = local_node_id << 16; - - fw_notify("reconnected to unit %s (%d retries)\n", - unit->device.bus_id, sd->retries); - sbp2_agent_reset(unit); - sbp2_cancel_orbs(unit); - kref_put(&sd->kref, release_sbp2_device); -} - -static void sbp2_update(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - - sd->retries = 0; - fw_device_enable_phys_dma(device); - if (schedule_delayed_work(&sd->work, 0)) - kref_get(&sd->kref); -} - -#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e -#define SBP2_SW_VERSION_ENTRY 0x00010483 - -static const struct fw_device_id sbp2_id_table[] = { - { - .match_flags = FW_MATCH_SPECIFIER_ID | FW_MATCH_VERSION, - .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY, - .version = SBP2_SW_VERSION_ENTRY, - }, - { } -}; - -static struct fw_driver sbp2_driver = { - .driver = { - .owner = THIS_MODULE, - .name = sbp2_driver_name, - .bus = &fw_bus_type, - .probe = sbp2_probe, - .remove = sbp2_remove, - }, - .update = sbp2_update, - .id_table = sbp2_id_table, -}; - -static unsigned int -sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) -{ - int sam_status; - - sense_data[0] = 0x70; - sense_data[1] = 0x0; - sense_data[2] = sbp2_status[1]; - sense_data[3] = sbp2_status[4]; - sense_data[4] = sbp2_status[5]; - sense_data[5] = sbp2_status[6]; - sense_data[6] = sbp2_status[7]; - sense_data[7] = 10; - sense_data[8] = sbp2_status[8]; - sense_data[9] = sbp2_status[9]; - sense_data[10] = sbp2_status[10]; - sense_data[11] = sbp2_status[11]; - sense_data[12] = sbp2_status[2]; - sense_data[13] = sbp2_status[3]; - sense_data[14] = sbp2_status[12]; - sense_data[15] = sbp2_status[13]; - - sam_status = sbp2_status[0] & 0x3f; - - switch (sam_status) { - case SAM_STAT_GOOD: - case SAM_STAT_CHECK_CONDITION: - case SAM_STAT_CONDITION_MET: - case SAM_STAT_BUSY: - case SAM_STAT_RESERVATION_CONFLICT: - case SAM_STAT_COMMAND_TERMINATED: - return DID_OK << 16 | sam_status; - - default: - return DID_ERROR << 16; - } -} - -static void -complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -{ - struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb; - struct fw_unit *unit = orb->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct scatterlist *sg; - int result; - - if (status != NULL) { - if (STATUS_GET_DEAD(*status)) - sbp2_agent_reset(unit); - - switch (STATUS_GET_RESPONSE(*status)) { - case SBP2_STATUS_REQUEST_COMPLETE: - result = DID_OK << 16; - break; - case SBP2_STATUS_TRANSPORT_FAILURE: - result = DID_BUS_BUSY << 16; - break; - case SBP2_STATUS_ILLEGAL_REQUEST: - case SBP2_STATUS_VENDOR_DEPENDENT: - default: - result = DID_ERROR << 16; - break; - } - - if (result == DID_OK << 16 && STATUS_GET_LEN(*status) > 1) - result = sbp2_status_to_sense_data(STATUS_GET_DATA(*status), - orb->cmd->sense_buffer); - } else { - /* - * If the orb completes with status == NULL, something - * went wrong, typically a bus reset happened mid-orb - * or when sending the write (less likely). - */ - result = DID_BUS_BUSY << 16; - } - - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - - if (orb->cmd->use_sg > 0) { - sg = (struct scatterlist *)orb->cmd->request_buffer; - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - } - - if (orb->page_table_bus != 0) - dma_unmap_single(device->card->device, orb->page_table_bus, - sizeof(orb->page_table_bus), DMA_TO_DEVICE); - - if (orb->request_buffer_bus != 0) - dma_unmap_single(device->card->device, orb->request_buffer_bus, - sizeof(orb->request_buffer_bus), - DMA_FROM_DEVICE); - - orb->cmd->result = result; - orb->done(orb->cmd); - kfree(orb); -} - -static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) -{ - struct sbp2_device *sd = - (struct sbp2_device *)orb->cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct scatterlist *sg; - int sg_len, l, i, j, count; - size_t size; - dma_addr_t sg_addr; - - sg = (struct scatterlist *)orb->cmd->request_buffer; - count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - if (count == 0) - goto fail; - - /* - * Handle the special case where there is only one element in - * the scatter list by converting it to an immediate block - * request. This is also a workaround for broken devices such - * as the second generation iPod which doesn't support page - * tables. - */ - if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { - orb->request.data_descriptor.high = sd->address_high; - orb->request.data_descriptor.low = sg_dma_address(sg); - orb->request.misc |= - COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); - return 0; - } - - /* - * Convert the scatterlist to an sbp2 page table. If any - * scatterlist entries are too big for sbp2, we split them as we - * go. Even if we ask the block I/O layer to not give us sg - * elements larger than 65535 bytes, some IOMMUs may merge sg elements - * during DMA mapping, and Linux currently doesn't prevent this. - */ - for (i = 0, j = 0; i < count; i++) { - sg_len = sg_dma_len(sg + i); - sg_addr = sg_dma_address(sg + i); - while (sg_len) { - l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH); - orb->page_table[j].low = sg_addr; - orb->page_table[j].high = (l << 16); - sg_addr += l; - sg_len -= l; - j++; - } - } - - size = sizeof(orb->page_table[0]) * j; - - /* - * The data_descriptor pointer is the one case where we need - * to fill in the node ID part of the address. All other - * pointers assume that the data referenced reside on the - * initiator (i.e. us), but data_descriptor can refer to data - * on other nodes so we need to put our ID in descriptor.high. - */ - - orb->page_table_bus = - dma_map_single(device->card->device, orb->page_table, - size, DMA_TO_DEVICE); - if (dma_mapping_error(orb->page_table_bus)) - goto fail_page_table; - orb->request.data_descriptor.high = sd->address_high; - orb->request.data_descriptor.low = orb->page_table_bus; - orb->request.misc |= - COMMAND_ORB_PAGE_TABLE_PRESENT | - COMMAND_ORB_DATA_SIZE(j); - - fw_memcpy_to_be32(orb->page_table, orb->page_table, size); - - return 0; - - fail_page_table: - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - fail: - return -ENOMEM; -} - -/* SCSI stack integration */ - -static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) -{ - struct sbp2_device *sd = - (struct sbp2_device *)cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_command_orb *orb; - - /* - * Bidirectional commands are not yet implemented, and unknown - * transfer direction not handled. - */ - if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { - fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); - cmd->result = DID_ERROR << 16; - done(cmd); - return 0; - } - - orb = kzalloc(sizeof(*orb), GFP_ATOMIC); - if (orb == NULL) { - fw_notify("failed to alloc orb\n"); - goto fail_alloc; - } - - /* Initialize rcode to something not RCODE_COMPLETE. */ - orb->base.rcode = -1; - orb->base.request_bus = - dma_map_single(device->card->device, &orb->request, - sizeof(orb->request), DMA_TO_DEVICE); - if (dma_mapping_error(orb->base.request_bus)) - goto fail_mapping; - - orb->unit = unit; - orb->done = done; - orb->cmd = cmd; - - orb->request.next.high = SBP2_ORB_NULL; - orb->request.next.low = 0x0; - /* - * At speed 100 we can do 512 bytes per packet, at speed 200, - * 1024 bytes per packet etc. The SBP-2 max_payload field - * specifies the max payload size as 2 ^ (max_payload + 2), so - * if we set this to max_speed + 7, we get the right value. - */ - orb->request.misc = - COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | - COMMAND_ORB_SPEED(device->node->max_speed) | - COMMAND_ORB_NOTIFY; - - if (cmd->sc_data_direction == DMA_FROM_DEVICE) - orb->request.misc |= - COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA); - else if (cmd->sc_data_direction == DMA_TO_DEVICE) - orb->request.misc |= - COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); - - if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0) - goto fail_map_payload; - - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); - - memset(orb->request.command_block, - 0, sizeof(orb->request.command_block)); - memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); - - orb->base.callback = complete_command_orb; - - sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation, - sd->command_block_agent_address + SBP2_ORB_POINTER); - - return 0; - - fail_map_payload: - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - fail_mapping: - kfree(orb); - fail_alloc: - return SCSI_MLQUEUE_HOST_BUSY; -} - -static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) -{ - struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; - - sdev->allow_restart = 1; - - if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36) - sdev->inquiry_len = 36; - return 0; -} - -static int sbp2_scsi_slave_configure(struct scsi_device *sdev) -{ - struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; - struct fw_unit *unit = sd->unit; - - sdev->use_10_for_rw = 1; - - if (sdev->type == TYPE_ROM) - sdev->use_10_for_ms = 1; - if (sdev->type == TYPE_DISK && - sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) - sdev->skip_ms_page_8 = 1; - if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) { - fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); - sdev->fix_capacity = 1; - } - - return 0; -} - -/* - * Called by scsi stack when something has really gone wrong. Usually - * called when a command has timed-out for some reason. - */ -static int sbp2_scsi_abort(struct scsi_cmnd *cmd) -{ - struct sbp2_device *sd = - (struct sbp2_device *)cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - - fw_notify("sbp2_scsi_abort\n"); - sbp2_agent_reset(unit); - sbp2_cancel_orbs(unit); - - return SUCCESS; -} - -static struct scsi_host_template scsi_driver_template = { - .module = THIS_MODULE, - .name = "SBP-2 IEEE-1394", - .proc_name = (char *)sbp2_driver_name, - .queuecommand = sbp2_scsi_queuecommand, - .slave_alloc = sbp2_scsi_slave_alloc, - .slave_configure = sbp2_scsi_slave_configure, - .eh_abort_handler = sbp2_scsi_abort, - .this_id = -1, - .sg_tablesize = SG_ALL, - .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = 1, - .can_queue = 1, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("SCSI over IEEE1394"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); - -/* Provide a module alias so root-on-sbp2 initrds don't break. */ -#ifndef CONFIG_IEEE1394_SBP2_MODULE -MODULE_ALIAS("sbp2"); -#endif - -static int __init sbp2_init(void) -{ - return driver_register(&sbp2_driver.driver); -} - -static void __exit sbp2_cleanup(void) -{ - driver_unregister(&sbp2_driver.driver); -} - -module_init(sbp2_init); -module_exit(sbp2_cleanup); diff --git a/trunk/drivers/firewire/fw-topology.c b/trunk/drivers/firewire/fw-topology.c deleted file mode 100644 index 7aebb8ae0efa..000000000000 --- a/trunk/drivers/firewire/fw-topology.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Incremental bus scan, based on bus topology - * - * Copyright (C) 2004-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" - -#define SELF_ID_PHY_ID(q) (((q) >> 24) & 0x3f) -#define SELF_ID_EXTENDED(q) (((q) >> 23) & 0x01) -#define SELF_ID_LINK_ON(q) (((q) >> 22) & 0x01) -#define SELF_ID_GAP_COUNT(q) (((q) >> 16) & 0x3f) -#define SELF_ID_PHY_SPEED(q) (((q) >> 14) & 0x03) -#define SELF_ID_CONTENDER(q) (((q) >> 11) & 0x01) -#define SELF_ID_PHY_INITIATOR(q) (((q) >> 1) & 0x01) -#define SELF_ID_MORE_PACKETS(q) (((q) >> 0) & 0x01) - -#define SELF_ID_EXT_SEQUENCE(q) (((q) >> 20) & 0x07) - -static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count) -{ - u32 q; - int port_type, shift, seq; - - *total_port_count = 0; - *child_port_count = 0; - - shift = 6; - q = *sid; - seq = 0; - - while (1) { - port_type = (q >> shift) & 0x03; - switch (port_type) { - case SELFID_PORT_CHILD: - (*child_port_count)++; - case SELFID_PORT_PARENT: - case SELFID_PORT_NCONN: - (*total_port_count)++; - case SELFID_PORT_NONE: - break; - } - - shift -= 2; - if (shift == 0) { - if (!SELF_ID_MORE_PACKETS(q)) - return sid + 1; - - shift = 16; - sid++; - q = *sid; - - /* - * Check that the extra packets actually are - * extended self ID packets and that the - * sequence numbers in the extended self ID - * packets increase as expected. - */ - - if (!SELF_ID_EXTENDED(q) || - seq != SELF_ID_EXT_SEQUENCE(q)) - return NULL; - - seq++; - } - } -} - -static int get_port_type(u32 *sid, int port_index) -{ - int index, shift; - - index = (port_index + 5) / 8; - shift = 16 - ((port_index + 5) & 7) * 2; - return (sid[index] >> shift) & 0x03; -} - -static struct fw_node *fw_node_create(u32 sid, int port_count, int color) -{ - struct fw_node *node; - - node = kzalloc(sizeof(*node) + port_count * sizeof(node->ports[0]), - GFP_ATOMIC); - if (node == NULL) - return NULL; - - node->color = color; - node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid); - node->link_on = SELF_ID_LINK_ON(sid); - node->phy_speed = SELF_ID_PHY_SPEED(sid); - node->port_count = port_count; - - atomic_set(&node->ref_count, 1); - INIT_LIST_HEAD(&node->link); - - return node; -} - -/* - * Compute the maximum hop count for this node and it's children. The - * maximum hop count is the maximum number of connections between any - * two nodes in the subtree rooted at this node. We need this for - * setting the gap count. As we build the tree bottom up in - * build_tree() below, this is fairly easy to do: for each node we - * maintain the max hop count and the max depth, ie the number of hops - * to the furthest leaf. Computing the max hop count breaks down into - * two cases: either the path goes through this node, in which case - * the hop count is the sum of the two biggest child depths plus 2. - * Or it could be the case that the max hop path is entirely - * containted in a child tree, in which case the max hop count is just - * the max hop count of this child. - */ -static void update_hop_count(struct fw_node *node) -{ - int depths[2] = { -1, -1 }; - int max_child_hops = 0; - int i; - - for (i = 0; i < node->port_count; i++) { - if (node->ports[i].node == NULL) - continue; - - if (node->ports[i].node->max_hops > max_child_hops) - max_child_hops = node->ports[i].node->max_hops; - - if (node->ports[i].node->max_depth > depths[0]) { - depths[1] = depths[0]; - depths[0] = node->ports[i].node->max_depth; - } else if (node->ports[i].node->max_depth > depths[1]) - depths[1] = node->ports[i].node->max_depth; - } - - node->max_depth = depths[0] + 1; - node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2); -} - - -/** - * build_tree - Build the tree representation of the topology - * @self_ids: array of self IDs to create the tree from - * @self_id_count: the length of the self_ids array - * @local_id: the node ID of the local node - * - * This function builds the tree representation of the topology given - * by the self IDs from the latest bus reset. During the construction - * of the tree, the function checks that the self IDs are valid and - * internally consistent. On succcess this funtions returns the - * fw_node corresponding to the local card otherwise NULL. - */ -static struct fw_node *build_tree(struct fw_card *card, - u32 *sid, int self_id_count) -{ - struct fw_node *node, *child, *local_node, *irm_node; - struct list_head stack, *h; - u32 *next_sid, *end, q; - int i, port_count, child_port_count, phy_id, parent_count, stack_depth; - int gap_count, topology_type; - - local_node = NULL; - node = NULL; - INIT_LIST_HEAD(&stack); - stack_depth = 0; - end = sid + self_id_count; - phy_id = 0; - irm_node = NULL; - gap_count = SELF_ID_GAP_COUNT(*sid); - topology_type = 0; - - while (sid < end) { - next_sid = count_ports(sid, &port_count, &child_port_count); - - if (next_sid == NULL) { - fw_error("Inconsistent extended self IDs.\n"); - return NULL; - } - - q = *sid; - if (phy_id != SELF_ID_PHY_ID(q)) { - fw_error("PHY ID mismatch in self ID: %d != %d.\n", - phy_id, SELF_ID_PHY_ID(q)); - return NULL; - } - - if (child_port_count > stack_depth) { - fw_error("Topology stack underflow\n"); - return NULL; - } - - /* - * Seek back from the top of our stack to find the - * start of the child nodes for this node. - */ - for (i = 0, h = &stack; i < child_port_count; i++) - h = h->prev; - child = fw_node(h); - - node = fw_node_create(q, port_count, card->color); - if (node == NULL) { - fw_error("Out of memory while building topology."); - return NULL; - } - - if (phy_id == (card->node_id & 0x3f)) - local_node = node; - - if (SELF_ID_CONTENDER(q)) - irm_node = node; - - if (node->phy_speed == SCODE_BETA) - topology_type |= FW_TOPOLOGY_B; - else - topology_type |= FW_TOPOLOGY_A; - - parent_count = 0; - - for (i = 0; i < port_count; i++) { - switch (get_port_type(sid, i)) { - case SELFID_PORT_PARENT: - /* - * Who's your daddy? We dont know the - * parent node at this time, so we - * temporarily abuse node->color for - * remembering the entry in the - * node->ports array where the parent - * node should be. Later, when we - * handle the parent node, we fix up - * the reference. - */ - parent_count++; - node->color = i; - break; - - case SELFID_PORT_CHILD: - node->ports[i].node = child; - /* - * Fix up parent reference for this - * child node. - */ - child->ports[child->color].node = node; - child->color = card->color; - child = fw_node(child->link.next); - break; - } - } - - /* - * Check that the node reports exactly one parent - * port, except for the root, which of course should - * have no parents. - */ - if ((next_sid == end && parent_count != 0) || - (next_sid < end && parent_count != 1)) { - fw_error("Parent port inconsistency for node %d: " - "parent_count=%d\n", phy_id, parent_count); - return NULL; - } - - /* Pop the child nodes off the stack and push the new node. */ - __list_del(h->prev, &stack); - list_add_tail(&node->link, &stack); - stack_depth += 1 - child_port_count; - - /* - * If all PHYs does not report the same gap count - * setting, we fall back to 63 which will force a gap - * count reconfiguration and a reset. - */ - if (SELF_ID_GAP_COUNT(q) != gap_count) - gap_count = 63; - - update_hop_count(node); - - sid = next_sid; - phy_id++; - } - - card->root_node = node; - card->irm_node = irm_node; - card->gap_count = gap_count; - card->topology_type = topology_type; - - return local_node; -} - -typedef void (*fw_node_callback_t)(struct fw_card * card, - struct fw_node * node, - struct fw_node * parent); - -static void -for_each_fw_node(struct fw_card *card, struct fw_node *root, - fw_node_callback_t callback) -{ - struct list_head list; - struct fw_node *node, *next, *child, *parent; - int i; - - INIT_LIST_HEAD(&list); - - fw_node_get(root); - list_add_tail(&root->link, &list); - parent = NULL; - list_for_each_entry(node, &list, link) { - node->color = card->color; - - for (i = 0; i < node->port_count; i++) { - child = node->ports[i].node; - if (!child) - continue; - if (child->color == card->color) - parent = child; - else { - fw_node_get(child); - list_add_tail(&child->link, &list); - } - } - - callback(card, node, parent); - } - - list_for_each_entry_safe(node, next, &list, link) - fw_node_put(node); -} - -static void -report_lost_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) -{ - fw_node_event(card, node, FW_NODE_DESTROYED); - fw_node_put(node); -} - -static void -report_found_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) -{ - int b_path = (node->phy_speed == SCODE_BETA); - - if (parent != NULL) { - /* min() macro doesn't work here with gcc 3.4 */ - node->max_speed = parent->max_speed < node->phy_speed ? - parent->max_speed : node->phy_speed; - node->b_path = parent->b_path && b_path; - } else { - node->max_speed = node->phy_speed; - node->b_path = b_path; - } - - fw_node_event(card, node, FW_NODE_CREATED); -} - -void fw_destroy_nodes(struct fw_card *card) -{ - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - card->color++; - if (card->local_node != NULL) - for_each_fw_node(card, card->local_node, report_lost_node); - spin_unlock_irqrestore(&card->lock, flags); -} - -static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) -{ - struct fw_node *tree; - int i; - - tree = node1->ports[port].node; - node0->ports[port].node = tree; - for (i = 0; i < tree->port_count; i++) { - if (tree->ports[i].node == node1) { - tree->ports[i].node = node0; - break; - } - } -} - -/** - * update_tree - compare the old topology tree for card with the new - * one specified by root. Queue the nodes and mark them as either - * found, lost or updated. Update the nodes in the card topology tree - * as we go. - */ -static void -update_tree(struct fw_card *card, struct fw_node *root) -{ - struct list_head list0, list1; - struct fw_node *node0, *node1; - int i, event; - - INIT_LIST_HEAD(&list0); - list_add_tail(&card->local_node->link, &list0); - INIT_LIST_HEAD(&list1); - list_add_tail(&root->link, &list1); - - node0 = fw_node(list0.next); - node1 = fw_node(list1.next); - - while (&node0->link != &list0) { - - /* assert(node0->port_count == node1->port_count); */ - if (node0->link_on && !node1->link_on) - event = FW_NODE_LINK_OFF; - else if (!node0->link_on && node1->link_on) - event = FW_NODE_LINK_ON; - else - event = FW_NODE_UPDATED; - - node0->node_id = node1->node_id; - node0->color = card->color; - node0->link_on = node1->link_on; - node0->initiated_reset = node1->initiated_reset; - node0->max_hops = node1->max_hops; - node1->color = card->color; - fw_node_event(card, node0, event); - - if (card->root_node == node1) - card->root_node = node0; - if (card->irm_node == node1) - card->irm_node = node0; - - for (i = 0; i < node0->port_count; i++) { - if (node0->ports[i].node && node1->ports[i].node) { - /* - * This port didn't change, queue the - * connected node for further - * investigation. - */ - if (node0->ports[i].node->color == card->color) - continue; - list_add_tail(&node0->ports[i].node->link, - &list0); - list_add_tail(&node1->ports[i].node->link, - &list1); - } else if (node0->ports[i].node) { - /* - * The nodes connected here were - * unplugged; unref the lost nodes and - * queue FW_NODE_LOST callbacks for - * them. - */ - - for_each_fw_node(card, node0->ports[i].node, - report_lost_node); - node0->ports[i].node = NULL; - } else if (node1->ports[i].node) { - /* - * One or more node were connected to - * this port. Move the new nodes into - * the tree and queue FW_NODE_CREATED - * callbacks for them. - */ - move_tree(node0, node1, i); - for_each_fw_node(card, node0->ports[i].node, - report_found_node); - } - } - - node0 = fw_node(node0->link.next); - node1 = fw_node(node1->link.next); - } -} - -static void -update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) -{ - int node_count; - - card->topology_map[1]++; - node_count = (card->root_node->node_id & 0x3f) + 1; - card->topology_map[2] = (node_count << 16) | self_id_count; - card->topology_map[0] = (self_id_count + 2) << 16; - memcpy(&card->topology_map[3], self_ids, self_id_count * 4); - fw_compute_block_crc(card->topology_map); -} - -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 * self_ids) -{ - struct fw_node *local_node; - unsigned long flags; - - fw_flush_transactions(card); - - spin_lock_irqsave(&card->lock, flags); - - /* - * If the new topology has a different self_id_count the topology - * changed, either nodes were added or removed. In that case we - * reset the IRM reset counter. - */ - if (card->self_id_count != self_id_count) - card->bm_retries = 0; - - card->node_id = node_id; - card->generation = generation; - card->reset_jiffies = jiffies; - schedule_delayed_work(&card->work, 0); - - local_node = build_tree(card, self_ids, self_id_count); - - update_topology_map(card, self_ids, self_id_count); - - card->color++; - - if (local_node == NULL) { - fw_error("topology build failed\n"); - /* FIXME: We need to issue a bus reset in this case. */ - } else if (card->local_node == NULL) { - card->local_node = local_node; - for_each_fw_node(card, local_node, report_found_node); - } else { - update_tree(card, local_node); - } - - spin_unlock_irqrestore(&card->lock, flags); -} -EXPORT_SYMBOL(fw_core_handle_bus_reset); diff --git a/trunk/drivers/firewire/fw-topology.h b/trunk/drivers/firewire/fw-topology.h deleted file mode 100644 index 363b6cbcd0b3..000000000000 --- a/trunk/drivers/firewire/fw-topology.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 __fw_topology_h -#define __fw_topology_h - -enum { - FW_TOPOLOGY_A = 0x01, - FW_TOPOLOGY_B = 0x02, - FW_TOPOLOGY_MIXED = 0x03, -}; - -enum { - FW_NODE_CREATED = 0x00, - FW_NODE_UPDATED = 0x01, - FW_NODE_DESTROYED = 0x02, - FW_NODE_LINK_ON = 0x03, - FW_NODE_LINK_OFF = 0x04, -}; - -struct fw_port { - struct fw_node *node; - unsigned speed : 3; /* S100, S200, ... S3200 */ -}; - -struct fw_node { - u16 node_id; - u8 color; - u8 port_count; - unsigned link_on : 1; - unsigned initiated_reset : 1; - unsigned b_path : 1; - u8 phy_speed : 3; /* As in the self ID packet. */ - u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on - * the path from the local node to this node. */ - u8 max_depth : 4; /* Maximum depth to any leaf node */ - u8 max_hops : 4; /* Max hops in this sub tree */ - atomic_t ref_count; - - /* For serializing node topology into a list. */ - struct list_head link; - - /* Upper layer specific data. */ - void *data; - - struct fw_port ports[0]; -}; - -static inline struct fw_node * -fw_node(struct list_head *l) -{ - return list_entry(l, struct fw_node, link); -} - -static inline struct fw_node * -fw_node_get(struct fw_node *node) -{ - atomic_inc(&node->ref_count); - - return node; -} - -static inline void -fw_node_put(struct fw_node *node) -{ - if (atomic_dec_and_test(&node->ref_count)) - kfree(node); -} - -void -fw_destroy_nodes(struct fw_card *card); - -int -fw_compute_block_crc(u32 *block); - - -#endif /* __fw_topology_h */ diff --git a/trunk/drivers/firewire/fw-transaction.c b/trunk/drivers/firewire/fw-transaction.c deleted file mode 100644 index 80d0121463d0..000000000000 --- a/trunk/drivers/firewire/fw-transaction.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Core IEEE1394 transaction logic - * - * Copyright (C) 2004-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -#define HEADER_PRI(pri) ((pri) << 0) -#define HEADER_TCODE(tcode) ((tcode) << 4) -#define HEADER_RETRY(retry) ((retry) << 8) -#define HEADER_TLABEL(tlabel) ((tlabel) << 10) -#define HEADER_DESTINATION(destination) ((destination) << 16) -#define HEADER_SOURCE(source) ((source) << 16) -#define HEADER_RCODE(rcode) ((rcode) << 12) -#define HEADER_OFFSET_HIGH(offset_high) ((offset_high) << 0) -#define HEADER_DATA_LENGTH(length) ((length) << 16) -#define HEADER_EXTENDED_TCODE(tcode) ((tcode) << 0) - -#define HEADER_GET_TCODE(q) (((q) >> 4) & 0x0f) -#define HEADER_GET_TLABEL(q) (((q) >> 10) & 0x3f) -#define HEADER_GET_RCODE(q) (((q) >> 12) & 0x0f) -#define HEADER_GET_DESTINATION(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_SOURCE(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_OFFSET_HIGH(q) (((q) >> 0) & 0xffff) -#define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - -#define PHY_CONFIG_GAP_COUNT(gap_count) (((gap_count) << 16) | (1 << 22)) -#define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) -#define PHY_IDENTIFIER(id) ((id) << 30) - -static int -close_transaction(struct fw_transaction *transaction, - struct fw_card *card, int rcode, - u32 *payload, size_t length) -{ - struct fw_transaction *t; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t == transaction) { - list_del(&t->link); - card->tlabel_mask &= ~(1 << t->tlabel); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&t->link != &card->transaction_list) { - t->callback(card, rcode, payload, length, t->callback_data); - return 0; - } - - return -ENOENT; -} - -/* - * Only valid for transactions that are potentially pending (ie have - * been sent). - */ -int -fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction) -{ - /* - * Cancel the packet transmission if it's still queued. That - * will call the packet transmission callback which cancels - * the transaction. - */ - - if (card->driver->cancel_packet(card, &transaction->packet) == 0) - return 0; - - /* - * If the request packet has already been sent, we need to see - * if the transaction is still pending and remove it in that case. - */ - - return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); -} -EXPORT_SYMBOL(fw_cancel_transaction); - -static void -transmit_complete_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - struct fw_transaction *t = - container_of(packet, struct fw_transaction, packet); - - switch (status) { - case ACK_COMPLETE: - close_transaction(t, card, RCODE_COMPLETE, NULL, 0); - break; - case ACK_PENDING: - t->timestamp = packet->timestamp; - break; - case ACK_BUSY_X: - case ACK_BUSY_A: - case ACK_BUSY_B: - close_transaction(t, card, RCODE_BUSY, NULL, 0); - break; - case ACK_DATA_ERROR: - close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0); - break; - case ACK_TYPE_ERROR: - close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); - break; - default: - /* - * In this case the ack is really a juju specific - * rcode, so just forward that to the callback. - */ - close_transaction(t, card, status, NULL, 0); - break; - } -} - -static void -fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, - int node_id, int source_id, int generation, int speed, - unsigned long long offset, void *payload, size_t length) -{ - int ext_tcode; - - if (tcode > 0x10) { - ext_tcode = tcode - 0x10; - tcode = TCODE_LOCK_REQUEST; - } else - ext_tcode = 0; - - packet->header[0] = - HEADER_RETRY(RETRY_X) | - HEADER_TLABEL(tlabel) | - HEADER_TCODE(tcode) | - HEADER_DESTINATION(node_id); - packet->header[1] = - HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id); - packet->header[2] = - offset; - - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - packet->header[3] = *(u32 *)payload; - packet->header_length = 16; - packet->payload_length = 0; - break; - - case TCODE_LOCK_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - packet->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(ext_tcode); - packet->header_length = 16; - packet->payload = payload; - packet->payload_length = length; - break; - - case TCODE_READ_QUADLET_REQUEST: - packet->header_length = 12; - packet->payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST: - packet->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(ext_tcode); - packet->header_length = 16; - packet->payload_length = 0; - break; - } - - packet->speed = speed; - packet->generation = generation; - packet->ack = 0; -} - -/** - * This function provides low-level access to the IEEE1394 transaction - * logic. Most C programs would use either fw_read(), fw_write() or - * fw_lock() instead - those function are convenience wrappers for - * this function. The fw_send_request() function is primarily - * provided as a flexible, one-stop entry point for languages bindings - * and protocol bindings. - * - * FIXME: Document this function further, in particular the possible - * values for rcode in the callback. In short, we map ACK_COMPLETE to - * RCODE_COMPLETE, internal errors set errno and set rcode to - * RCODE_SEND_ERROR (which is out of range for standard ieee1394 - * rcodes). All other rcodes are forwarded unchanged. For all - * errors, payload is NULL, length is 0. - * - * Can not expect the callback to be called before the function - * returns, though this does happen in some cases (ACK_COMPLETE and - * errors). - * - * The payload is only used for write requests and must not be freed - * until the callback has been called. - * - * @param card the card from which to send the request - * @param tcode the tcode for this transaction. Do not use - * TCODE_LOCK_REQUEST directly, insted use TCODE_LOCK_MASK_SWAP - * etc. to specify tcode and ext_tcode. - * @param node_id the destination node ID (bus ID and PHY ID concatenated) - * @param generation the generation for which node_id is valid - * @param speed the speed to use for sending the request - * @param offset the 48 bit offset on the destination node - * @param payload the data payload for the request subaction - * @param length the length in bytes of the data to read - * @param callback function to be called when the transaction is completed - * @param callback_data pointer to arbitrary data, which will be - * passed to the callback - */ -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int node_id, int generation, int speed, - unsigned long long offset, - void *payload, size_t length, - fw_transaction_callback_t callback, void *callback_data) -{ - unsigned long flags; - int tlabel, source; - - /* - * Bump the flush timer up 100ms first of all so we - * don't race with a flush timer callback. - */ - - mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10)); - - /* - * Allocate tlabel from the bitmap and put the transaction on - * the list while holding the card spinlock. - */ - - spin_lock_irqsave(&card->lock, flags); - - source = card->node_id; - tlabel = card->current_tlabel; - if (card->tlabel_mask & (1 << tlabel)) { - spin_unlock_irqrestore(&card->lock, flags); - callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); - return; - } - - card->current_tlabel = (card->current_tlabel + 1) & 0x1f; - card->tlabel_mask |= (1 << tlabel); - - list_add_tail(&t->link, &card->transaction_list); - - spin_unlock_irqrestore(&card->lock, flags); - - /* Initialize rest of transaction, fill out packet and send it. */ - t->node_id = node_id; - t->tlabel = tlabel; - t->callback = callback; - t->callback_data = callback_data; - - fw_fill_request(&t->packet, tcode, t->tlabel, - node_id, source, generation, - speed, offset, payload, length); - t->packet.callback = transmit_complete_callback; - - card->driver->send_request(card, &t->packet); -} -EXPORT_SYMBOL(fw_send_request); - -static void -transmit_phy_packet_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - kfree(packet); -} - -static void send_phy_packet(struct fw_card *card, u32 data, int generation) -{ - struct fw_packet *packet; - - packet = kzalloc(sizeof(*packet), GFP_ATOMIC); - if (packet == NULL) - return; - - packet->header[0] = data; - packet->header[1] = ~data; - packet->header_length = 8; - packet->payload_length = 0; - packet->speed = SCODE_100; - packet->generation = generation; - packet->callback = transmit_phy_packet_callback; - - card->driver->send_request(card, packet); -} - -void fw_send_phy_config(struct fw_card *card, - int node_id, int generation, int gap_count) -{ - u32 q; - - q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) | - PHY_CONFIG_ROOT_ID(node_id) | - PHY_CONFIG_GAP_COUNT(gap_count); - - send_phy_packet(card, q, generation); -} - -void fw_flush_transactions(struct fw_card *card) -{ - struct fw_transaction *t, *next; - struct list_head list; - unsigned long flags; - - INIT_LIST_HEAD(&list); - spin_lock_irqsave(&card->lock, flags); - list_splice_init(&card->transaction_list, &list); - card->tlabel_mask = 0; - spin_unlock_irqrestore(&card->lock, flags); - - list_for_each_entry_safe(t, next, &list, link) { - card->driver->cancel_packet(card, &t->packet); - - /* - * At this point cancel_packet will never call the - * transaction callback, since we just took all the - * transactions out of the list. So do it here. - */ - t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); - } -} - -static struct fw_address_handler * -lookup_overlapping_address_handler(struct list_head *list, - unsigned long long offset, size_t length) -{ - struct fw_address_handler *handler; - - list_for_each_entry(handler, list, link) { - if (handler->offset < offset + length && - offset < handler->offset + handler->length) - return handler; - } - - return NULL; -} - -static struct fw_address_handler * -lookup_enclosing_address_handler(struct list_head *list, - unsigned long long offset, size_t length) -{ - struct fw_address_handler *handler; - - list_for_each_entry(handler, list, link) { - if (handler->offset <= offset && - offset + length <= handler->offset + handler->length) - return handler; - } - - return NULL; -} - -static DEFINE_SPINLOCK(address_handler_lock); -static LIST_HEAD(address_handler_list); - -const struct fw_address_region fw_low_memory_region = - { .start = 0x000000000000ULL, .end = 0x000100000000ULL, }; -const struct fw_address_region fw_high_memory_region = - { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, }; -const struct fw_address_region fw_private_region = - { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, }; -const struct fw_address_region fw_csr_region = - { .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL, }; -const struct fw_address_region fw_unit_space_region = - { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; -EXPORT_SYMBOL(fw_low_memory_region); -EXPORT_SYMBOL(fw_high_memory_region); -EXPORT_SYMBOL(fw_private_region); -EXPORT_SYMBOL(fw_csr_region); -EXPORT_SYMBOL(fw_unit_space_region); - -/** - * Allocate a range of addresses in the node space of the OHCI - * controller. When a request is received that falls within the - * specified address range, the specified callback is invoked. The - * parameters passed to the callback give the details of the - * particular request - */ -int -fw_core_add_address_handler(struct fw_address_handler *handler, - const struct fw_address_region *region) -{ - struct fw_address_handler *other; - unsigned long flags; - int ret = -EBUSY; - - spin_lock_irqsave(&address_handler_lock, flags); - - handler->offset = region->start; - while (handler->offset + handler->length <= region->end) { - other = - lookup_overlapping_address_handler(&address_handler_list, - handler->offset, - handler->length); - if (other != NULL) { - handler->offset += other->length; - } else { - list_add_tail(&handler->link, &address_handler_list); - ret = 0; - break; - } - } - - spin_unlock_irqrestore(&address_handler_lock, flags); - - return ret; -} -EXPORT_SYMBOL(fw_core_add_address_handler); - -/** - * Deallocate a range of addresses allocated with fw_allocate. This - * will call the associated callback one last time with a the special - * tcode TCODE_DEALLOCATE, to let the client destroy the registered - * callback data. For convenience, the callback parameters offset and - * length are set to the start and the length respectively for the - * deallocated region, payload is set to NULL. - */ -void fw_core_remove_address_handler(struct fw_address_handler *handler) -{ - unsigned long flags; - - spin_lock_irqsave(&address_handler_lock, flags); - list_del(&handler->link); - spin_unlock_irqrestore(&address_handler_lock, flags); -} -EXPORT_SYMBOL(fw_core_remove_address_handler); - -struct fw_request { - struct fw_packet response; - u32 request_header[4]; - int ack; - u32 length; - u32 data[0]; -}; - -static void -free_response_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - struct fw_request *request; - - request = container_of(packet, struct fw_request, response); - kfree(request); -} - -void -fw_fill_response(struct fw_packet *response, u32 *request_header, - int rcode, void *payload, size_t length) -{ - int tcode, tlabel, extended_tcode, source, destination; - - tcode = HEADER_GET_TCODE(request_header[0]); - tlabel = HEADER_GET_TLABEL(request_header[0]); - source = HEADER_GET_DESTINATION(request_header[0]); - destination = HEADER_GET_SOURCE(request_header[1]); - extended_tcode = HEADER_GET_EXTENDED_TCODE(request_header[3]); - - response->header[0] = - HEADER_RETRY(RETRY_1) | - HEADER_TLABEL(tlabel) | - HEADER_DESTINATION(destination); - response->header[1] = - HEADER_SOURCE(source) | - HEADER_RCODE(rcode); - response->header[2] = 0; - - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - response->header[0] |= HEADER_TCODE(TCODE_WRITE_RESPONSE); - response->header_length = 12; - response->payload_length = 0; - break; - - case TCODE_READ_QUADLET_REQUEST: - response->header[0] |= - HEADER_TCODE(TCODE_READ_QUADLET_RESPONSE); - if (payload != NULL) - response->header[3] = *(u32 *)payload; - else - response->header[3] = 0; - response->header_length = 16; - response->payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST: - case TCODE_LOCK_REQUEST: - response->header[0] |= HEADER_TCODE(tcode + 2); - response->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(extended_tcode); - response->header_length = 16; - response->payload = payload; - response->payload_length = length; - break; - - default: - BUG(); - return; - } -} -EXPORT_SYMBOL(fw_fill_response); - -static struct fw_request * -allocate_request(struct fw_packet *p) -{ - struct fw_request *request; - u32 *data, length; - int request_tcode, t; - - request_tcode = HEADER_GET_TCODE(p->header[0]); - switch (request_tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - data = &p->header[3]; - length = 4; - break; - - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_LOCK_REQUEST: - data = p->payload; - length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - case TCODE_READ_QUADLET_REQUEST: - data = NULL; - length = 4; - break; - - case TCODE_READ_BLOCK_REQUEST: - data = NULL; - length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - default: - BUG(); - return NULL; - } - - request = kmalloc(sizeof(*request) + length, GFP_ATOMIC); - if (request == NULL) - return NULL; - - t = (p->timestamp & 0x1fff) + 4000; - if (t >= 8000) - t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; - else - t = (p->timestamp & ~0x1fff) + t; - - request->response.speed = p->speed; - request->response.timestamp = t; - request->response.generation = p->generation; - request->response.ack = 0; - request->response.callback = free_response_callback; - request->ack = p->ack; - request->length = length; - if (data) - memcpy(request->data, data, length); - - memcpy(request->request_header, p->header, sizeof(p->header)); - - return request; -} - -void -fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) -{ - /* - * Broadcast packets are reported as ACK_COMPLETE, so this - * check is sufficient to ensure we don't send response to - * broadcast packets or posted writes. - */ - if (request->ack != ACK_PENDING) - return; - - if (rcode == RCODE_COMPLETE) - fw_fill_response(&request->response, request->request_header, - rcode, request->data, request->length); - else - fw_fill_response(&request->response, request->request_header, - rcode, NULL, 0); - - card->driver->send_response(card, &request->response); -} -EXPORT_SYMBOL(fw_send_response); - -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *p) -{ - struct fw_address_handler *handler; - struct fw_request *request; - unsigned long long offset; - unsigned long flags; - int tcode, destination, source; - - if (p->payload_length > 2048) { - /* FIXME: send error response. */ - return; - } - - if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) - return; - - request = allocate_request(p); - if (request == NULL) { - /* FIXME: send statically allocated busy packet. */ - return; - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2]; - tcode = HEADER_GET_TCODE(p->header[0]); - destination = HEADER_GET_DESTINATION(p->header[0]); - source = HEADER_GET_SOURCE(p->header[0]); - - spin_lock_irqsave(&address_handler_lock, flags); - handler = lookup_enclosing_address_handler(&address_handler_list, - offset, request->length); - spin_unlock_irqrestore(&address_handler_lock, flags); - - /* - * FIXME: lookup the fw_node corresponding to the sender of - * this request and pass that to the address handler instead - * of the node ID. We may also want to move the address - * allocations to fw_node so we only do this callback if the - * upper layers registered it for this node. - */ - - if (handler == NULL) - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - else - handler->address_callback(card, request, - tcode, destination, source, - p->generation, p->speed, offset, - request->data, request->length, - handler->callback_data); -} -EXPORT_SYMBOL(fw_core_handle_request); - -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *p) -{ - struct fw_transaction *t; - unsigned long flags; - u32 *data; - size_t data_length; - int tcode, tlabel, destination, source, rcode; - - tcode = HEADER_GET_TCODE(p->header[0]); - tlabel = HEADER_GET_TLABEL(p->header[0]); - destination = HEADER_GET_DESTINATION(p->header[0]); - source = HEADER_GET_SOURCE(p->header[1]); - rcode = HEADER_GET_RCODE(p->header[1]); - - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t->node_id == source && t->tlabel == tlabel) { - list_del(&t->link); - card->tlabel_mask &= ~(1 << t->tlabel); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&t->link == &card->transaction_list) { - fw_notify("Unsolicited response (source %x, tlabel %x)\n", - source, tlabel); - return; - } - - /* - * FIXME: sanity check packet, is length correct, does tcodes - * and addresses match. - */ - - switch (tcode) { - case TCODE_READ_QUADLET_RESPONSE: - data = (u32 *) &p->header[3]; - data_length = 4; - break; - - case TCODE_WRITE_RESPONSE: - data = NULL; - data_length = 0; - break; - - case TCODE_READ_BLOCK_RESPONSE: - case TCODE_LOCK_RESPONSE: - data = p->payload; - data_length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - default: - /* Should never happen, this is just to shut up gcc. */ - data = NULL; - data_length = 0; - break; - } - - t->callback(card, rcode, data, data_length, t->callback_data); -} -EXPORT_SYMBOL(fw_core_handle_response); - -const struct fw_address_region topology_map_region = - { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, }; - -static void -handle_topology_map(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - int i, start, end; - u32 *map; - - if (!TCODE_IS_READ_REQUEST(tcode)) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - return; - } - - if ((offset & 3) > 0 || (length & 3) > 0) { - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - return; - } - - start = (offset - topology_map_region.start) / 4; - end = start + length / 4; - map = payload; - - for (i = 0; i < length / 4; i++) - map[i] = cpu_to_be32(card->topology_map[start + i]); - - fw_send_response(card, request, RCODE_COMPLETE); -} - -static struct fw_address_handler topology_map = { - .length = 0x200, - .address_callback = handle_topology_map, -}; - -const struct fw_address_region registers_region = - { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, }; - -static void -handle_registers(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - int reg = offset - CSR_REGISTER_BASE; - unsigned long long bus_time; - __be32 *data = payload; - - switch (reg) { - case CSR_CYCLE_TIME: - case CSR_BUS_TIME: - if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - break; - } - - bus_time = card->driver->get_bus_time(card); - if (reg == CSR_CYCLE_TIME) - *data = cpu_to_be32(bus_time); - else - *data = cpu_to_be32(bus_time >> 25); - fw_send_response(card, request, RCODE_COMPLETE); - break; - - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: - /* - * FIXME: these are handled by the OHCI hardware and - * the stack never sees these request. If we add - * support for a new type of controller that doesn't - * handle this in hardware we need to deal with these - * transactions. - */ - BUG(); - break; - - case CSR_BUSY_TIMEOUT: - /* FIXME: Implement this. */ - default: - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - break; - } -} - -static struct fw_address_handler registers = { - .length = 0x400, - .address_callback = handle_registers, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); -MODULE_LICENSE("GPL"); - -static const u32 vendor_textual_descriptor[] = { - /* textual descriptor leaf () */ - 0x00060000, - 0x00000000, - 0x00000000, - 0x4c696e75, /* L i n u */ - 0x78204669, /* x F i */ - 0x72657769, /* r e w i */ - 0x72650000, /* r e */ -}; - -static const u32 model_textual_descriptor[] = { - /* model descriptor leaf () */ - 0x00030000, - 0x00000000, - 0x00000000, - 0x4a756a75, /* J u j u */ -}; - -static struct fw_descriptor vendor_id_descriptor = { - .length = ARRAY_SIZE(vendor_textual_descriptor), - .immediate = 0x03d00d1e, - .key = 0x81000000, - .data = vendor_textual_descriptor, -}; - -static struct fw_descriptor model_id_descriptor = { - .length = ARRAY_SIZE(model_textual_descriptor), - .immediate = 0x17000001, - .key = 0x81000000, - .data = model_textual_descriptor, -}; - -static int __init fw_core_init(void) -{ - int retval; - - retval = bus_register(&fw_bus_type); - if (retval < 0) - return retval; - - fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); - if (fw_cdev_major < 0) { - bus_unregister(&fw_bus_type); - return fw_cdev_major; - } - - retval = fw_core_add_address_handler(&topology_map, - &topology_map_region); - BUG_ON(retval < 0); - - retval = fw_core_add_address_handler(®isters, - ®isters_region); - BUG_ON(retval < 0); - - /* Add the vendor textual descriptor. */ - retval = fw_core_add_descriptor(&vendor_id_descriptor); - BUG_ON(retval < 0); - retval = fw_core_add_descriptor(&model_id_descriptor); - BUG_ON(retval < 0); - - return 0; -} - -static void __exit fw_core_cleanup(void) -{ - unregister_chrdev(fw_cdev_major, "firewire"); - bus_unregister(&fw_bus_type); -} - -module_init(fw_core_init); -module_exit(fw_core_cleanup); diff --git a/trunk/drivers/firewire/fw-transaction.h b/trunk/drivers/firewire/fw-transaction.h deleted file mode 100644 index acdc3be38c61..000000000000 --- a/trunk/drivers/firewire/fw-transaction.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 __fw_transaction_h -#define __fw_transaction_h - -#include -#include -#include -#include -#include -#include -#include - -#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) -#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) -#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) -#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0) -#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4) -#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0) - -#define LOCAL_BUS 0xffc0 - -#define SELFID_PORT_CHILD 0x3 -#define SELFID_PORT_PARENT 0x2 -#define SELFID_PORT_NCONN 0x1 -#define SELFID_PORT_NONE 0x0 - -#define PHY_PACKET_CONFIG 0x0 -#define PHY_PACKET_LINK_ON 0x1 -#define PHY_PACKET_SELF_ID 0x2 - -/* Bit fields _within_ the PHY registers. */ -#define PHY_LINK_ACTIVE 0x80 -#define PHY_CONTENDER 0x40 -#define PHY_BUS_RESET 0x40 -#define PHY_BUS_SHORT_RESET 0x40 - -#define CSR_REGISTER_BASE 0xfffff0000000ULL - -/* register offsets relative to CSR_REGISTER_BASE */ -#define CSR_STATE_CLEAR 0x0 -#define CSR_STATE_SET 0x4 -#define CSR_NODE_IDS 0x8 -#define CSR_RESET_START 0xc -#define CSR_SPLIT_TIMEOUT_HI 0x18 -#define CSR_SPLIT_TIMEOUT_LO 0x1c -#define CSR_CYCLE_TIME 0x200 -#define CSR_BUS_TIME 0x204 -#define CSR_BUSY_TIMEOUT 0x210 -#define CSR_BUS_MANAGER_ID 0x21c -#define CSR_BANDWIDTH_AVAILABLE 0x220 -#define CSR_CHANNELS_AVAILABLE 0x224 -#define CSR_CHANNELS_AVAILABLE_HI 0x224 -#define CSR_CHANNELS_AVAILABLE_LO 0x228 -#define CSR_BROADCAST_CHANNEL 0x234 -#define CSR_CONFIG_ROM 0x400 -#define CSR_CONFIG_ROM_END 0x800 -#define CSR_FCP_COMMAND 0xB00 -#define CSR_FCP_RESPONSE 0xD00 -#define CSR_FCP_END 0xF00 -#define CSR_TOPOLOGY_MAP 0x1000 -#define CSR_TOPOLOGY_MAP_END 0x1400 -#define CSR_SPEED_MAP 0x2000 -#define CSR_SPEED_MAP_END 0x3000 - -#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) -#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) -#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args) - -static inline void -fw_memcpy_from_be32(void *_dst, void *_src, size_t size) -{ - u32 *dst = _dst; - u32 *src = _src; - int i; - - for (i = 0; i < size / 4; i++) - dst[i] = cpu_to_be32(src[i]); -} - -static inline void -fw_memcpy_to_be32(void *_dst, void *_src, size_t size) -{ - fw_memcpy_from_be32(_dst, _src, size); -} - -struct fw_card; -struct fw_packet; -struct fw_node; -struct fw_request; - -struct fw_descriptor { - struct list_head link; - size_t length; - u32 immediate; - u32 key; - const u32 *data; -}; - -int fw_core_add_descriptor(struct fw_descriptor *desc); -void fw_core_remove_descriptor(struct fw_descriptor *desc); - -typedef void (*fw_packet_callback_t)(struct fw_packet *packet, - struct fw_card *card, int status); - -typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, - void *data, - size_t length, - void *callback_data); - -typedef void (*fw_address_callback_t)(struct fw_card *card, - struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *data, size_t length, - void *callback_data); - -typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, - int node_id, int generation, - u32 *self_ids, - int self_id_count, - void *callback_data); - -struct fw_packet { - int speed; - int generation; - u32 header[4]; - size_t header_length; - void *payload; - size_t payload_length; - u32 timestamp; - - /* - * This callback is called when the packet transmission has - * completed; for successful transmission, the status code is - * the ack received from the destination, otherwise it's a - * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. - * The callback can be called from tasklet context and thus - * must never block. - */ - fw_packet_callback_t callback; - int ack; - struct list_head link; - void *driver_data; -}; - -struct fw_transaction { - int node_id; /* The generation is implied; it is always the current. */ - int tlabel; - int timestamp; - struct list_head link; - - struct fw_packet packet; - - /* - * The data passed to the callback is valid only during the - * callback. - */ - fw_transaction_callback_t callback; - void *callback_data; -}; - -static inline struct fw_packet * -fw_packet(struct list_head *l) -{ - return list_entry(l, struct fw_packet, link); -} - -struct fw_address_handler { - u64 offset; - size_t length; - fw_address_callback_t address_callback; - void *callback_data; - struct list_head link; -}; - - -struct fw_address_region { - u64 start; - u64 end; -}; - -extern const struct fw_address_region fw_low_memory_region; -extern const struct fw_address_region fw_high_memory_region; -extern const struct fw_address_region fw_private_region; -extern const struct fw_address_region fw_csr_region; -extern const struct fw_address_region fw_unit_space_region; - -int fw_core_add_address_handler(struct fw_address_handler *handler, - const struct fw_address_region *region); -void fw_core_remove_address_handler(struct fw_address_handler *handler); -void fw_fill_response(struct fw_packet *response, u32 *request_header, - int rcode, void *payload, size_t length); -void fw_send_response(struct fw_card *card, - struct fw_request *request, int rcode); - -extern struct bus_type fw_bus_type; - -struct fw_card { - const struct fw_card_driver *driver; - struct device *device; - struct kref kref; - - int node_id; - int generation; - /* This is the generation used for timestamping incoming requests. */ - int request_generation; - int current_tlabel, tlabel_mask; - struct list_head transaction_list; - struct timer_list flush_timer; - unsigned long reset_jiffies; - - unsigned long long guid; - int max_receive; - int link_speed; - int config_rom_generation; - - /* - * We need to store up to 4 self ID for a maximum of 63 - * devices plus 3 words for the topology map header. - */ - int self_id_count; - u32 topology_map[252 + 3]; - - spinlock_t lock; /* Take this lock when handling the lists in - * this struct. */ - struct fw_node *local_node; - struct fw_node *root_node; - struct fw_node *irm_node; - int color; - int gap_count; - int topology_type; - - int index; - - struct list_head link; - - /* Work struct for BM duties. */ - struct delayed_work work; - int bm_retries; - int bm_generation; -}; - -struct fw_card *fw_card_get(struct fw_card *card); -void fw_card_put(struct fw_card *card); - -/* - * The iso packet format allows for an immediate header/payload part - * stored in 'header' immediately after the packet info plus an - * indirect payload part that is pointer to by the 'payload' field. - * Applications can use one or the other or both to implement simple - * low-bandwidth streaming (e.g. audio) or more advanced - * scatter-gather streaming (e.g. assembling video frame automatically). - */ - -struct fw_iso_packet { - u16 payload_length; /* Length of indirect payload. */ - u32 interrupt : 1; /* Generate interrupt on this packet */ - u32 skip : 1; /* Set to not send packet at all. */ - u32 tag : 2; - u32 sy : 4; - u32 header_length : 8; /* Length of immediate header. */ - u32 header[0]; -}; - -#define FW_ISO_CONTEXT_TRANSMIT 0 -#define FW_ISO_CONTEXT_RECEIVE 1 - -#define FW_ISO_CONTEXT_MATCH_TAG0 1 -#define FW_ISO_CONTEXT_MATCH_TAG1 2 -#define FW_ISO_CONTEXT_MATCH_TAG2 4 -#define FW_ISO_CONTEXT_MATCH_TAG3 8 -#define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15 - -struct fw_iso_context; - -typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, - u32 cycle, - size_t header_length, - void *header, - void *data); - -/* - * An iso buffer is just a set of pages mapped for DMA in the - * specified direction. Since the pages are to be used for DMA, they - * are not mapped into the kernel virtual address space. We store the - * DMA address in the page private. The helper function - * fw_iso_buffer_map() will map the pages into a given vma. - */ - -struct fw_iso_buffer { - enum dma_data_direction direction; - struct page **pages; - int page_count; -}; - -struct fw_iso_context { - struct fw_card *card; - int type; - int channel; - int speed; - size_t header_size; - fw_iso_callback_t callback; - void *callback_data; -}; - -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, - struct fw_card *card, - int page_count, - enum dma_data_direction direction); -int -fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); -void -fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); - -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data); - -void -fw_iso_context_destroy(struct fw_iso_context *ctx); - -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload); - -int -fw_iso_context_start(struct fw_iso_context *ctx, - int cycle, int sync, int tags); - -int -fw_iso_context_stop(struct fw_iso_context *ctx); - -struct fw_card_driver { - const char *name; - - /* - * Enable the given card with the given initial config rom. - * This function is expected to activate the card, and either - * enable the PHY or set the link_on bit and initiate a bus - * reset. - */ - int (*enable)(struct fw_card *card, u32 *config_rom, size_t length); - - int (*update_phy_reg)(struct fw_card *card, int address, - int clear_bits, int set_bits); - - /* - * Update the config rom for an enabled card. This function - * should change the config rom that is presented on the bus - * an initiate a bus reset. - */ - int (*set_config_rom)(struct fw_card *card, - u32 *config_rom, size_t length); - - void (*send_request)(struct fw_card *card, struct fw_packet *packet); - void (*send_response)(struct fw_card *card, struct fw_packet *packet); - /* Calling cancel is valid once a packet has been submitted. */ - int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet); - - /* - * Allow the specified node ID to do direct DMA out and in of - * host memory. The card will disable this for all node when - * a bus reset happens, so driver need to reenable this after - * bus reset. Returns 0 on success, -ENODEV if the card - * doesn't support this, -ESTALE if the generation doesn't - * match. - */ - int (*enable_phys_dma)(struct fw_card *card, - int node_id, int generation); - - u64 (*get_bus_time)(struct fw_card *card); - - struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, - int type, size_t header_size); - void (*free_iso_context)(struct fw_iso_context *ctx); - - int (*start_iso)(struct fw_iso_context *ctx, - s32 cycle, u32 sync, u32 tags); - - int (*queue_iso)(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload); - - int (*stop_iso)(struct fw_iso_context *ctx); -}; - -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); - -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int node_id, int generation, int speed, - unsigned long long offset, - void *data, size_t length, - fw_transaction_callback_t callback, void *callback_data); - -int fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction); - -void fw_flush_transactions(struct fw_card *card); - -void fw_send_phy_config(struct fw_card *card, - int node_id, int generation, int gap_count); - -/* - * Called by the topology code to inform the device code of node - * activity; found, lost, or updated nodes. - */ -void -fw_node_event(struct fw_card *card, struct fw_node *node, int event); - -/* API used by card level drivers */ - -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device); -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid); - -void -fw_core_remove_card(struct fw_card *card); - -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 *self_ids); -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *request); - -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); - -#endif /* __fw_transaction_h */ diff --git a/trunk/drivers/hid/hid-input.c b/trunk/drivers/hid/hid-input.c index a19b65ed3119..52de9a914a82 100644 --- a/trunk/drivers/hid/hid-input.c +++ b/trunk/drivers/hid/hid-input.c @@ -553,6 +553,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1015: map_key_clear(KEY_RECORD); break; case 0x1016: map_key_clear(KEY_PLAYER); break; case 0x1017: map_key_clear(KEY_EJECTCD); break; + case 0x1018: map_key_clear(KEY_MEDIA); break; case 0x1019: map_key_clear(KEY_PROG1); break; case 0x101a: map_key_clear(KEY_PROG2); break; case 0x101b: map_key_clear(KEY_PROG3); break; @@ -560,9 +561,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1020: map_key_clear(KEY_ZOOMOUT); break; case 0x1021: map_key_clear(KEY_ZOOMRESET); break; case 0x1023: map_key_clear(KEY_CLOSE); break; + case 0x1027: map_key_clear(KEY_MENU); break; /* this one is marked as 'Rotate' */ case 0x1028: map_key_clear(KEY_ANGLE); break; case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x102a: map_key_clear(KEY_BACK); break; + case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break; case 0x1041: map_key_clear(KEY_BATTERY); break; case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; case 0x1043: map_key_clear(KEY_SPREADSHEET); break; diff --git a/trunk/drivers/hwmon/Kconfig b/trunk/drivers/hwmon/Kconfig index 4d1cb5b855d1..3ba3a5221c41 100644 --- a/trunk/drivers/hwmon/Kconfig +++ b/trunk/drivers/hwmon/Kconfig @@ -4,7 +4,6 @@ menuconfig HWMON tristate "Hardware Monitoring support" - depends on HAS_IOMEM default y help Hardware monitoring devices let you monitor the hardware health diff --git a/trunk/drivers/hwmon/ams/ams-input.c b/trunk/drivers/hwmon/ams/ams-input.c index ca7095d96ad0..18210164e307 100644 --- a/trunk/drivers/hwmon/ams/ams-input.c +++ b/trunk/drivers/hwmon/ams/ams-input.c @@ -87,7 +87,7 @@ static void ams_input_enable(void) ams_info.idev->id.vendor = 0; ams_info.idev->open = ams_input_open; ams_info.idev->close = ams_input_close; - ams_info.idev->dev.parent = &ams_info.of_dev->dev; + ams_info.idev->cdev.dev = &ams_info.of_dev->dev; input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0); input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0); diff --git a/trunk/drivers/hwmon/applesmc.c b/trunk/drivers/hwmon/applesmc.c index 0c160675b3ac..3215f9c87f32 100644 --- a/trunk/drivers/hwmon/applesmc.c +++ b/trunk/drivers/hwmon/applesmc.c @@ -981,7 +981,7 @@ static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \ static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \ applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \ \ -static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \ +static SENSOR_DEVICE_ATTR(fan##offset##_position, S_IRUGO, \ applesmc_show_fan_position, NULL, offset-1); \ \ static struct attribute *fan##offset##_attributes[] = { \ @@ -991,7 +991,7 @@ static struct attribute *fan##offset##_attributes[] = { \ &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \ &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \ - &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \ + &sensor_dev_attr_fan##offset##_position.dev_attr.attr, \ NULL \ }; @@ -1100,7 +1100,7 @@ static int applesmc_create_accelerometer(void) /* initialize the input class */ applesmc_idev->name = "applesmc"; applesmc_idev->id.bustype = BUS_HOST; - applesmc_idev->dev.parent = &pdev->dev; + applesmc_idev->cdev.dev = &pdev->dev; applesmc_idev->evbit[0] = BIT(EV_ABS); applesmc_idev->open = applesmc_idev_open; applesmc_idev->close = applesmc_idev_close; @@ -1190,8 +1190,7 @@ static int __init applesmc_init(void) if (ret) goto out_region; - pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, - NULL, 0); + pdev = platform_device_register_simple("applesmc", -1, NULL, 0); if (IS_ERR(pdev)) { ret = PTR_ERR(pdev); goto out_driver; diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index 75e3911810a3..03b1f650d1c4 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -309,11 +309,9 @@ static int coretemp_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: coretemp_device_add(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: coretemp_device_remove(cpu); break; } diff --git a/trunk/drivers/hwmon/hdaps.c b/trunk/drivers/hwmon/hdaps.c index e0cf5e6fe5bc..f82fa2d23f95 100644 --- a/trunk/drivers/hwmon/hdaps.c +++ b/trunk/drivers/hwmon/hdaps.c @@ -574,7 +574,7 @@ static int __init hdaps_init(void) /* initialize the input class */ hdaps_idev->name = "hdaps"; - hdaps_idev->dev.parent = &pdev->dev; + hdaps_idev->cdev.dev = &pdev->dev; hdaps_idev->evbit[0] = BIT(EV_ABS); input_set_abs_params(hdaps_idev, ABS_X, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); diff --git a/trunk/drivers/i2c/Kconfig b/trunk/drivers/i2c/Kconfig index 96867347bcbf..434a61b415a3 100644 --- a/trunk/drivers/i2c/Kconfig +++ b/trunk/drivers/i2c/Kconfig @@ -4,7 +4,6 @@ menuconfig I2C tristate "I2C support" - depends on HAS_IOMEM ---help--- I2C (pronounce: I-square-C) is a slow serial bus protocol used in many micro controller applications and developed by Philips. SMBus, diff --git a/trunk/drivers/i2c/busses/i2c-at91.c b/trunk/drivers/i2c/busses/i2c-at91.c index 9c8b6d5eaec9..f35156c58922 100644 --- a/trunk/drivers/i2c/busses/i2c-at91.c +++ b/trunk/drivers/i2c/busses/i2c-at91.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -227,14 +226,13 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev) adapter->algo = &at91_algorithm; adapter->class = I2C_CLASS_HWMON; adapter->dev.parent = &pdev->dev; - /* adapter->id == 0 ... only one TWI controller for now */ platform_set_drvdata(pdev, adapter); clk_enable(twi_clk); /* enable peripheral clock */ at91_twi_hwinit(); /* initialize TWI controller */ - rc = i2c_add_numbered_adapter(adapter); + rc = i2c_add_adapter(adapter); if (rc) { dev_err(&pdev->dev, "Adapter %s registration failed\n", adapter->name); @@ -297,9 +295,6 @@ static int at91_i2c_resume(struct platform_device *pdev) #define at91_i2c_resume NULL #endif -/* work with "modprobe at91_i2c" from hotplugging or coldplugging */ -MODULE_ALIAS("at91_i2c"); - static struct platform_driver at91_i2c_driver = { .probe = at91_i2c_probe, .remove = __devexit_p(at91_i2c_remove), diff --git a/trunk/drivers/i2c/busses/i2c-pxa.c b/trunk/drivers/i2c/busses/i2c-pxa.c index 8a0a99b93641..873544ab598e 100644 --- a/trunk/drivers/i2c/busses/i2c-pxa.c +++ b/trunk/drivers/i2c/busses/i2c-pxa.c @@ -548,7 +548,7 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) */ icr = readl(_ICR(i2c)); icr &= ~(ICR_STOP | ICR_ACKNAK); - writel(icr, _ICR(i2c)); + writel(icr, _IRC(i2c)); } /* diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 3c3f2ebf3fc9..7ed92dc3d833 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -354,7 +354,7 @@ static void tps65010_interrupt(struct tps65010 *tps) * also needs to get error handling and probably * an #ifdef CONFIG_SOFTWARE_SUSPEND */ - hibernate(); + pm_suspend(PM_SUSPEND_DISK); #endif poll = 1; } diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 9040809d2c25..5bdf64b77913 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -7,7 +7,6 @@ if BLOCK menu "ATA/ATAPI/MFM/RLL support" - depends on HAS_IOMEM config IDE tristate "ATA/ATAPI/MFM/RLL support" @@ -292,17 +291,6 @@ config IDE_TASK_IOCTL If you are unsure, say N here. -config IDE_PROC_FS - bool "legacy /proc/ide/ support" - depends on IDE && PROC_FS - default y - help - This option enables support for the various files in - /proc/ide. In Linux 2.6 this has been superseded by - files in sysfs but many legacy applications rely on this. - - If unsure say Y. - comment "IDE chipset support/bugfixes" config IDE_GENERIC @@ -372,9 +360,6 @@ config IDEPCI_SHARE_IRQ It is safe to say Y to this question, in most cases. If unsure, say N. -config IDEPCI_PCIBUS_ORDER - def_bool PCI && BLK_DEV_IDE=y && BLK_DEV_IDEPCI - config BLK_DEV_OFFBOARD bool "Boot off-board chipsets first support" depends on PCI && BLK_DEV_IDEPCI diff --git a/trunk/drivers/ide/Makefile b/trunk/drivers/ide/Makefile index 75dc6969e0a7..d9f029e8ff74 100644 --- a/trunk/drivers/ide/Makefile +++ b/trunk/drivers/ide/Makefile @@ -20,7 +20,7 @@ ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o # Core IDE code - must come before legacy ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o -ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o +ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o diff --git a/trunk/drivers/ide/arm/bast-ide.c b/trunk/drivers/ide/arm/bast-ide.c index f7449d04114a..9d474e5fd8dc 100644 --- a/trunk/drivers/ide/arm/bast-ide.c +++ b/trunk/drivers/ide/arm/bast-ide.c @@ -45,7 +45,7 @@ bastide_register(unsigned int base, unsigned int aux, int irq, hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); hw.irq = irq; - ide_register_hw(&hw, 0, hwif); + ide_register_hw(&hw, hwif); return 0; } diff --git a/trunk/drivers/ide/arm/icside.c b/trunk/drivers/ide/arm/icside.c index 1fe0457243db..e2953fc1fafb 100644 --- a/trunk/drivers/ide/arm/icside.c +++ b/trunk/drivers/ide/arm/icside.c @@ -342,7 +342,7 @@ static int icside_dma_check(ide_drive_t *drive) * Enable DMA on any drive that has multiword DMA */ if (id->field_valid & 2) { - xfer_mode = ide_max_dma_mode(drive); + xfer_mode = ide_dma_speed(drive, 0); goto out; } @@ -591,8 +591,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) state->hwif[0] = hwif; probe_hwif_init(hwif); - - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 0; } @@ -680,9 +679,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) probe_hwif_init(hwif); probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; diff --git a/trunk/drivers/ide/arm/ide_arm.c b/trunk/drivers/ide/arm/ide_arm.c index a3d6744e870a..23488c4d1fcd 100644 --- a/trunk/drivers/ide/arm/ide_arm.c +++ b/trunk/drivers/ide/arm/ide_arm.c @@ -38,6 +38,6 @@ void __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, 1, NULL); + ide_register_hw(&hw, NULL); } } diff --git a/trunk/drivers/ide/arm/rapide.c b/trunk/drivers/ide/arm/rapide.c index 890ea3fac3c6..9c6c49fdd2b1 100644 --- a/trunk/drivers/ide/arm/rapide.c +++ b/trunk/drivers/ide/arm/rapide.c @@ -76,7 +76,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) hwif->gendev.parent = &ec->dev; hwif->noprobe = 0; probe_hwif_init(hwif); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); ecard_set_drvdata(ec, hwif); goto out; } diff --git a/trunk/drivers/ide/cris/ide-cris.c b/trunk/drivers/ide/cris/ide-cris.c index c04cb25a01ff..5e8efc89255a 100644 --- a/trunk/drivers/ide/cris/ide-cris.c +++ b/trunk/drivers/ide/cris/ide-cris.c @@ -796,7 +796,7 @@ init_e100_ide (void) ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); - ide_register_hw(&hw, 1, &hwif); + ide_register_hw(&hw, &hwif); hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->tuneproc = &tune_cris_ide; @@ -1004,7 +1004,7 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) static int cris_config_drive_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, 1); if (!speed) return 0; diff --git a/trunk/drivers/ide/h8300/ide-h8300.c b/trunk/drivers/ide/h8300/ide-h8300.c index 6d26ad7360d5..88750a300337 100644 --- a/trunk/drivers/ide/h8300/ide-h8300.c +++ b/trunk/drivers/ide/h8300/ide-h8300.c @@ -101,7 +101,7 @@ void __init h8300_ide_init(void) hw_setup(&hw); /* register if */ - idx = ide_register_hw(&hw, 1, &hwif); + idx = ide_register_hw(&hw, &hwif); if (idx == -1) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); return; diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index 252ab8295edf..638becda81c6 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -3059,14 +3059,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) return nslots; } -#ifdef CONFIG_IDE_PROC_FS static void ide_cdrom_add_settings(ide_drive_t *drive) { - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } -#else -static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } -#endif /* * standard prep_rq_fn that builds 10 byte cmds @@ -3278,7 +3274,7 @@ int ide_cdrom_setup (ide_drive_t *drive) return 0; } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static sector_t ide_cdrom_capacity (ide_drive_t *drive) { @@ -3295,7 +3291,7 @@ static void ide_cd_remove(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; - ide_proc_unregister_driver(drive, info->driver); + ide_unregister_subdriver(drive, info->driver); del_gendisk(info->disk); @@ -3325,7 +3321,7 @@ static void ide_cd_release(struct kref *kref) static int ide_cd_probe(ide_drive_t *); -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static int proc_idecd_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -3340,6 +3336,8 @@ static ide_proc_entry_t idecd_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; +#else +# define idecd_proc NULL #endif static ide_driver_t ide_cdrom_driver = { @@ -3357,9 +3355,7 @@ static ide_driver_t ide_cdrom_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idecd_proc, -#endif }; static int idecd_open(struct inode * inode, struct file * file) @@ -3521,7 +3517,7 @@ static int ide_cd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &ide_cdrom_driver); + ide_register_subdriver(drive, &ide_cdrom_driver); kref_init(&info->kref); @@ -3538,7 +3534,7 @@ static int ide_cd_probe(ide_drive_t *drive) g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; - ide_proc_unregister_driver(drive, &ide_cdrom_driver); + ide_unregister_subdriver(drive, &ide_cdrom_driver); kfree(info->buffer); kfree(info->toc); kfree(info->changer_info); diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 7fff773f2df7..37aa6ddd9702 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -559,7 +559,8 @@ static sector_t idedisk_capacity (ide_drive_t *drive) return drive->capacity64 - drive->sect0; } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int smart_enable(ide_drive_t *drive) { ide_task_t args; @@ -677,7 +678,12 @@ static ide_proc_entry_t idedisk_proc[] = { { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, { NULL, 0, NULL, NULL } }; -#endif /* CONFIG_IDE_PROC_FS */ + +#else + +#define idedisk_proc NULL + +#endif /* CONFIG_PROC_FS */ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) { @@ -731,9 +737,6 @@ static int set_multcount(ide_drive_t *drive, int arg) { struct request rq; - if (arg < 0 || arg > drive->id->max_multsect) - return -EINVAL; - if (drive->special.b.set_multmode) return -EBUSY; ide_init_drive_cmd (&rq); @@ -746,9 +749,6 @@ static int set_multcount(ide_drive_t *drive, int arg) static int set_nowerr(ide_drive_t *drive, int arg) { - if (arg < 0 || arg > 1) - return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) return -EBUSY; drive->nowerr = arg; @@ -800,9 +800,6 @@ static int write_cache(ide_drive_t *drive, int arg) ide_task_t args; int err = 1; - if (arg < 0 || arg > 1) - return -EINVAL; - if (ide_id_has_flush_cache(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? @@ -838,9 +835,6 @@ static int set_acoustic (ide_drive_t *drive, int arg) { ide_task_t args; - if (arg < 0 || arg > 254) - return -EINVAL; - memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; @@ -861,9 +855,6 @@ static int set_acoustic (ide_drive_t *drive, int arg) */ static int set_lba_addressing(ide_drive_t *drive, int arg) { - if (arg < 0 || arg > 2) - return -EINVAL; - drive->addressing = 0; if (HWIF(drive)->no_lba48) @@ -875,27 +866,23 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) return 0; } -#ifdef CONFIG_IDE_PROC_FS static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); - ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); - ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); + ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); + ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); + ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); + ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); + ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); + ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); + ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); + ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } -#else -static inline void idedisk_add_settings(ide_drive_t *drive) { ; } -#endif static void idedisk_setup (ide_drive_t *drive) { @@ -1014,7 +1001,7 @@ static void ide_disk_remove(ide_drive_t *drive) struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; - ide_proc_unregister_driver(drive, idkp->driver); + ide_unregister_subdriver(drive, idkp->driver); del_gendisk(g); @@ -1079,9 +1066,7 @@ static ide_driver_t idedisk_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idedisk_proc, -#endif }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1155,49 +1140,9 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long flags; struct block_device *bdev = inode->i_bdev; struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - ide_drive_t *drive = idkp->drive; - int err, (*setfunc)(ide_drive_t *, int); - u8 *val; - - switch (cmd) { - case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; - case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; - case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; - case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; - case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; - case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; - case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; - case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; - case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; - case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; - } - - return generic_ide_ioctl(drive, file, bdev, cmd, arg); - -read_val: - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - err = *val; - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - down(&ide_setting_sem); - err = setfunc(drive, arg); - up(&ide_setting_sem); - } - } - return err; + return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); } static int idedisk_media_changed(struct gendisk *disk) @@ -1257,7 +1202,7 @@ static int ide_disk_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idedisk_driver); + ide_register_subdriver(drive, &idedisk_driver); kref_init(&idkp->kref); diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index 5fe85191d49c..fd213088b06b 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -705,100 +705,6 @@ int ide_use_dma(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_use_dma); -static const u8 xfer_mode_bases[] = { - XFER_UDMA_0, - XFER_MW_DMA_0, - XFER_SW_DMA_0, -}; - -static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = drive->hwif; - unsigned int mask = 0; - - switch(base) { - case XFER_UDMA_0: - if ((id->field_valid & 4) == 0) - break; - - mask = id->dma_ultra & hwif->ultra_mask; - - if (hwif->udma_filter) - mask &= hwif->udma_filter(drive); - - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - break; - case XFER_MW_DMA_0: - mask = id->dma_mword & hwif->mwdma_mask; - break; - case XFER_SW_DMA_0: - mask = id->dma_1word & hwif->swdma_mask; - break; - default: - BUG(); - break; - } - - return mask; -} - -/** - * ide_max_dma_mode - compute DMA speed - * @drive: IDE device - * - * Checks the drive capabilities and returns the speed to use - * for the DMA transfer. Returns 0 if the drive is incapable - * of DMA transfers. - */ - -u8 ide_max_dma_mode(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned int mask; - int x, i; - u8 mode = 0; - - if (drive->media != ide_disk && hwif->atapi_dma == 0) - return 0; - - for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { - mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); - x = fls(mask) - 1; - if (x >= 0) { - mode = xfer_mode_bases[i] + x; - break; - } - } - - printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); - - return mode; -} - -EXPORT_SYMBOL_GPL(ide_max_dma_mode); - -int ide_tune_dma(ide_drive_t *drive) -{ - u8 speed; - - /* TODO: use only ide_max_dma_mode() */ - if (!ide_use_dma(drive)) - return 0; - - speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - drive->hwif->speedproc(drive, speed); - - return ide_dma_enable(drive); -} - -EXPORT_SYMBOL_GPL(ide_tune_dma); - void ide_dma_verbose(ide_drive_t *drive) { struct hd_driveid *id = drive->id; diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c index f429be88c4f9..57cd21c5b2c1 100644 --- a/trunk/drivers/ide/ide-floppy.c +++ b/trunk/drivers/ide/ide-floppy.c @@ -1811,22 +1811,18 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) return 0; } -#ifdef CONFIG_IDE_PROC_FS static void idefloppy_add_settings(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); } -#else -static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } -#endif /* * Driver initialization. @@ -1877,7 +1873,7 @@ static void ide_floppy_remove(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; - ide_proc_unregister_driver(drive, floppy->driver); + ide_unregister_subdriver(drive, floppy->driver); del_gendisk(g); @@ -1896,7 +1892,8 @@ static void ide_floppy_release(struct kref *kref) kfree(floppy); } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int proc_idefloppy_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1912,7 +1909,12 @@ static ide_proc_entry_t idefloppy_proc[] = { { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; -#endif /* CONFIG_IDE_PROC_FS */ + +#else + +#define idefloppy_proc NULL + +#endif /* CONFIG_PROC_FS */ static int ide_floppy_probe(ide_drive_t *); @@ -1931,9 +1933,7 @@ static ide_driver_t idefloppy_driver = { .end_request = idefloppy_do_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idefloppy_proc, -#endif }; static int idefloppy_open(struct inode *inode, struct file *filp) @@ -2159,7 +2159,7 @@ static int ide_floppy_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idefloppy_driver); + ide_register_subdriver(drive, &idefloppy_driver); kref_init(&floppy->kref); diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c index 0f72b98d727f..99fd56151131 100644 --- a/trunk/drivers/ide/ide-generic.c +++ b/trunk/drivers/ide/ide-generic.c @@ -22,6 +22,8 @@ static int __init ide_generic_init(void) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_release_lock(); /* for atari only */ + create_proc_ide_interfaces(); + return 0; } diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index 8e568143d90d..8670112f1d39 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -172,6 +172,15 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * memset(args, 0, sizeof(*args)); + if (drive->media != ide_disk) { + /* + * skip idedisk_pm_restore_pio and idedisk_pm_idle for ATAPI + * devices + */ + if (pm->pm_step == idedisk_pm_restore_pio) + pm->pm_step = ide_pm_restore_dma; + } + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ if (drive->media != ide_disk) @@ -198,13 +207,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ if (drive->hwif->tuneproc != NULL) drive->hwif->tuneproc(drive, 255); - /* - * skip idedisk_pm_idle for ATAPI devices - */ - if (drive->media != ide_disk) - pm->pm_step = ide_pm_restore_dma; - else - ide_complete_power_step(drive, rq, 0, 0); + ide_complete_power_step(drive, rq, 0, 0); return ide_stopped; case idedisk_pm_idle: /* Resume step 2 (idle) */ diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index f0be5f665a0e..3caa176b3155 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -571,54 +571,51 @@ EXPORT_SYMBOL(ide_wait_stat); */ u8 eighty_ninty_three (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; - - if (hwif->udma_four == 0) - goto no_80w; + if(HWIF(drive)->udma_four == 0) + return 0; /* Check for SATA but only if we are ATA5 or higher */ - if (id->hw_config == 0 && (id->major_rev_num & 0x7FE0)) + if (drive->id->hw_config == 0 && (drive->id->major_rev_num & 0x7FE0)) return 1; - + if (!(drive->id->hw_config & 0x6000)) + return 0; +#ifndef CONFIG_IDEDMA_IVB + if(!(drive->id->hw_config & 0x4000)) + return 0; +#endif /* CONFIG_IDEDMA_IVB */ /* * FIXME: * - change master/slave IDENTIFY order * - force bit13 (80c cable present) check * (unless the slave device is pre-ATA3) */ -#ifndef CONFIG_IDEDMA_IVB - if (id->hw_config & 0x4000) -#else - if (id->hw_config & 0x6000) -#endif - return 1; - -no_80w: - if (drive->udma33_warned == 1) - return 0; - - printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, " - "limiting max speed to UDMA33\n", - drive->name, hwif->udma_four ? "drive" : "host"); - - drive->udma33_warned = 1; - - return 0; + return 1; } +EXPORT_SYMBOL(eighty_ninty_three); + int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) { if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (eighty_ninty_three(drive) == 0) { - printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " - "be set\n", drive->name); +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ + if (((drive->id->hw_config & 0x2000) == 0) || + ((drive->id->hw_config & 0x4000) == 0)) { +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", drive->name); + return 1; + } + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", + HWIF(drive)->name); return 1; } } - return 0; } diff --git a/trunk/drivers/ide/ide-lib.c b/trunk/drivers/ide/ide-lib.c index 3be3c69383f2..68719314df3f 100644 --- a/trunk/drivers/ide/ide-lib.c +++ b/trunk/drivers/ide/ide-lib.c @@ -69,41 +69,123 @@ char *ide_xfer_verbose (u8 xfer_rate) EXPORT_SYMBOL(ide_xfer_verbose); /** - * ide_rate_filter - filter transfer mode - * @drive: IDE device + * ide_dma_speed - compute DMA speed + * @drive: drive + * @mode: modes available + * + * Checks the drive capabilities and returns the speed to use + * for the DMA transfer. Returns 0 if the drive is incapable + * of DMA transfers. + */ + +u8 ide_dma_speed(ide_drive_t *drive, u8 mode) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + u8 ultra_mask, mwdma_mask, swdma_mask; + u8 speed = 0; + + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return 0; + + /* Capable of UltraDMA modes? */ + ultra_mask = id->dma_ultra & hwif->ultra_mask; + + if (!(id->field_valid & 4)) + mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ + + switch (mode) { + case 4: + if (ultra_mask & 0x40) { + speed = XFER_UDMA_6; + break; + } + case 3: + if (ultra_mask & 0x20) { + speed = XFER_UDMA_5; + break; + } + case 2: + if (ultra_mask & 0x10) { + speed = XFER_UDMA_4; + break; + } + if (ultra_mask & 0x08) { + speed = XFER_UDMA_3; + break; + } + case 1: + if (ultra_mask & 0x04) { + speed = XFER_UDMA_2; + break; + } + if (ultra_mask & 0x02) { + speed = XFER_UDMA_1; + break; + } + if (ultra_mask & 0x01) { + speed = XFER_UDMA_0; + break; + } + case 0: + mwdma_mask = id->dma_mword & hwif->mwdma_mask; + + if (mwdma_mask & 0x04) { + speed = XFER_MW_DMA_2; + break; + } + if (mwdma_mask & 0x02) { + speed = XFER_MW_DMA_1; + break; + } + if (mwdma_mask & 0x01) { + speed = XFER_MW_DMA_0; + break; + } + + swdma_mask = id->dma_1word & hwif->swdma_mask; + + if (swdma_mask & 0x04) { + speed = XFER_SW_DMA_2; + break; + } + if (swdma_mask & 0x02) { + speed = XFER_SW_DMA_1; + break; + } + if (swdma_mask & 0x01) { + speed = XFER_SW_DMA_0; + break; + } + } + + return speed; +} +EXPORT_SYMBOL(ide_dma_speed); + + +/** + * ide_rate_filter - return best speed for mode + * @mode: modes available * @speed: desired speed * - * Given the available transfer modes this function returns + * Given the available DMA/UDMA mode this function returns * the best available speed at or below the speed requested. - * - * FIXME: filter also PIO/SWDMA/MWDMA modes */ -u8 ide_rate_filter(ide_drive_t *drive, u8 speed) +u8 ide_rate_filter (u8 mode, u8 speed) { #ifdef CONFIG_BLK_DEV_IDEDMA - ide_hwif_t *hwif = drive->hwif; - u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; - - if (hwif->udma_filter) - mask = hwif->udma_filter(drive); - - /* - * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false - * cable warning from eighty_ninty_three(), moving ide_rate_filter() - * calls from ->speedproc to core code will make this hack go away - */ - if (speed > XFER_UDMA_2) { - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - } - - if (mask) - mode = fls(mask) - 1 + XFER_UDMA_0; + static u8 speed_max[] = { + XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, + XFER_UDMA_5, XFER_UDMA_6 + }; // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); - return min(speed, mode); + /* So that we remember to update this if new modes appear */ + BUG_ON(mode > 4); + return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ return min(speed, (u8)XFER_PIO_4); #endif /* CONFIG_BLK_DEV_IDEDMA */ diff --git a/trunk/drivers/ide/ide-pnp.c b/trunk/drivers/ide/ide-pnp.c index 2b8009c50e91..98410ca044cf 100644 --- a/trunk/drivers/ide/ide-pnp.c +++ b/trunk/drivers/ide/ide-pnp.c @@ -42,7 +42,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id hw.irq = pnp_irq(dev, 0); hw.dma = NO_DMA; - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 3cebed77f55d..8f15c23aa70d 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1427,9 +1427,6 @@ int ideprobe_init (void) } } } - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - ide_proc_register_port(&ide_hwifs[index]); return 0; } diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c index d50bd996ff22..a9e0b30fb1f2 100644 --- a/trunk/drivers/ide/ide-proc.c +++ b/trunk/drivers/ide/ide-proc.c @@ -3,8 +3,6 @@ * * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 2003 Red Hat - * - * Some code was moved here from ide.c, see it for original copyrights. */ /* @@ -39,8 +37,6 @@ #include -static struct proc_dir_entry *proc_ide_root; - static int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -125,265 +121,6 @@ static int proc_ide_read_identify PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -/** - * __ide_add_setting - add an ide setting option - * @drive: drive to use - * @name: setting name - * @rw: true if the function is read write - * @data_type: type of data - * @min: range minimum - * @max: range maximum - * @mul_factor: multiplication scale - * @div_factor: divison scale - * @data: private data field - * @set: setting - * @auto_remove: setting auto removal flag - * - * Removes the setting named from the device if it is present. - * The function takes the settings_lock to protect against - * parallel changes. This function must not be called from IRQ - * context. Returns 0 on success or -1 on failure. - * - * BUGS: This code is seriously over-engineered. There is also - * magic about how the driver specific features are setup. If - * a driver is attached we assume the driver settings are auto - * remove. - */ - -static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - down(&ide_setting_sem); - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); - setting->rw = rw; - setting->data_type = data_type; - setting->min = min; - setting->max = max; - setting->mul_factor = mul_factor; - setting->div_factor = div_factor; - setting->data = data; - setting->set = set; - - setting->next = *p; - if (auto_remove) - setting->auto_remove = 1; - *p = setting; - up(&ide_setting_sem); - return 0; -abort: - up(&ide_setting_sem); - kfree(setting); - return -1; -} - -int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); -} - -EXPORT_SYMBOL(ide_add_setting); - -/** - * __ide_remove_setting - remove an ide setting option - * @drive: drive to use - * @name: setting name - * - * Removes the setting named from the device if it is present. - * The caller must hold the setting semaphore. - */ - -static void __ide_remove_setting (ide_drive_t *drive, char *name) -{ - ide_settings_t **p, *setting; - - p = (ide_settings_t **) &drive->settings; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - if ((setting = (*p)) == NULL) - return; - - (*p) = setting->next; - - kfree(setting->name); - kfree(setting); -} - -/** - * auto_remove_settings - remove driver specific settings - * @drive: drive - * - * Automatically remove all the driver specific settings for this - * drive. This function may not be called from IRQ context. The - * caller must hold ide_setting_sem. - */ - -static void auto_remove_settings (ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - __ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -/** - * ide_find_setting_by_name - find a drive specific setting - * @drive: drive to scan - * @name: setting name - * - * Scan's the device setting table for a matching entry and returns - * this or NULL if no entry is found. The caller must hold the - * setting semaphore - */ - -static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) - break; - setting = setting->next; - } - return setting; -} - -/** - * ide_read_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * - * Read a drive setting and return the value. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - */ - -static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) -{ - int val = -EINVAL; - unsigned long flags; - - if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&ide_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - val = *((u32 *) setting->data); - break; - } - spin_unlock_irqrestore(&ide_lock, flags); - } - return val; -} - -/** - * ide_write_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * @val: value - * - * Write a drive setting if it is possible. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - * - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgy, though safe enough. - */ - -static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) -{ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (setting->set) - return setting->set(drive, val); - if (!(setting->rw & SETTING_WRITE)) - return -EPERM; - if (val < setting->min || val > setting->max) - return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - } - spin_unlock_irq(&ide_lock); - return 0; -} - -static int set_xfer_rate (ide_drive_t *drive, int arg) -{ - int err; - - if (arg < 0 || arg > 70) - return -EINVAL; - - err = ide_wait_cmd(drive, - WIN_SETFEATURES, (u8) arg, - SETFEATURES_XFER, 0, NULL); - - if (!err && arg) { - ide_set_xfer_rate(drive, (u8) arg); - ide_driveid_update(drive); - } - return err; -} - -/** - * ide_add_generic_settings - generic ide settings - * @drive: drive being configured - * - * Add the generic parts of the system settings to the /proc files. - * The caller must not be holding the ide_setting_sem. - */ - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access data type min max mul_factor div_factor data pointer set function - */ - __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); - __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); - __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); - __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); - __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); - __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); - __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); -} - static void proc_ide_settings_warn(void) { static int warned = 0; @@ -662,7 +399,7 @@ static ide_proc_entry_t generic_drive_entries[] = { { NULL, 0, NULL, NULL } }; -static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) +void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) { struct proc_dir_entry *ent; @@ -678,7 +415,7 @@ static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p } } -static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) +void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) { if (!dir || !p) return; @@ -688,51 +425,6 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t } } -void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) -{ - ide_add_proc_entries(drive->proc, driver->proc, drive); -} - -EXPORT_SYMBOL(ide_proc_register_driver); - -/** - * ide_proc_unregister_driver - remove driver specific data - * @drive: drive - * @driver: driver - * - * Clean up the driver specific /proc files and IDE settings - * for a given drive. - * - * Takes ide_setting_sem and ide_lock. - * Caller must hold none of the locks. - */ - -void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) -{ - unsigned long flags; - - ide_remove_proc_entries(drive->proc, driver->proc); - - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - /* - * ide_setting_sem protects the settings list - * ide_lock protects the use of settings - * - * so we need to hold both, ide_settings_sem because we want to - * modify the settings list, and ide_lock because we cannot take - * a setting out that is being used. - * - * OTOH both ide_{read,write}_setting are only ever used under - * ide_setting_sem. - */ - auto_remove_settings(drive); - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); -} - -EXPORT_SYMBOL(ide_proc_unregister_driver); - static void create_proc_ide_drives(ide_hwif_t *hwif) { int d; @@ -785,24 +477,26 @@ static ide_proc_entry_t hwif_entries[] = { { NULL, 0, NULL, NULL } }; -void ide_proc_register_port(ide_hwif_t *hwif) +void create_proc_ide_interfaces(void) { - if (!hwif->present) - return; - - if (!hwif->proc) { - hwif->proc = proc_mkdir(hwif->name, proc_ide_root); + int h; - if (!hwif->proc) - return; + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; - ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + if (!hwif->present) + continue; + if (!hwif->proc) { + hwif->proc = proc_mkdir(hwif->name, proc_ide_root); + if (!hwif->proc) + return; + ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + } + create_proc_ide_drives(hwif); } - - create_proc_ide_drives(hwif); } -EXPORT_SYMBOL_GPL(ide_proc_register_port); +EXPORT_SYMBOL(create_proc_ide_interfaces); #ifdef CONFIG_BLK_DEV_IDEPCI void ide_pci_create_host_proc(const char *name, get_info_t *get_info) @@ -813,7 +507,7 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info) EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); #endif -void ide_proc_unregister_port(ide_hwif_t *hwif) +void destroy_proc_ide_interface(ide_hwif_t *hwif) { if (hwif->proc) { destroy_proc_ide_drives(hwif); @@ -860,11 +554,11 @@ void proc_ide_create(void) { struct proc_dir_entry *entry; - proc_ide_root = proc_mkdir("ide", NULL); - if (!proc_ide_root) return; + create_proc_ide_interfaces(); + entry = create_proc_entry("drivers", 0, proc_ide_root); if (entry) entry->proc_fops = &ide_drivers_operations; diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c index e82bfa5e0ab8..4e59239fef75 100644 --- a/trunk/drivers/ide/ide-tape.c +++ b/trunk/drivers/ide/ide-tape.c @@ -4561,33 +4561,28 @@ static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); #endif /* IDETAPE_DEBUG_INFO */ } - -#ifdef CONFIG_IDE_PROC_FS static void idetape_add_settings (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); - ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); - ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); - ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); - ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); - ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); - ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed,NULL); - ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); - ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); + ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); + ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); + ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); + ide_add_setting(drive, "stage", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); + ide_add_setting(drive, "tdsc", SETTING_RW, -1, -1, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); + ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); + ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); + ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); } -#else -static inline void idetape_add_settings(ide_drive_t *drive) { ; } -#endif /* * ide_setup is called to: @@ -4708,7 +4703,7 @@ static void ide_tape_remove(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - ide_proc_unregister_driver(drive, tape->driver); + ide_unregister_subdriver(drive, tape->driver); ide_unregister_region(tape->disk); @@ -4735,7 +4730,8 @@ static void ide_tape_release(struct kref *kref) kfree(tape); } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int proc_idetape_read_name (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -4753,6 +4749,11 @@ static ide_proc_entry_t idetape_proc[] = { { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, { NULL, 0, NULL, NULL } }; + +#else + +#define idetape_proc NULL + #endif static int ide_tape_probe(ide_drive_t *); @@ -4772,9 +4773,7 @@ static ide_driver_t idetape_driver = { .end_request = idetape_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idetape_proc, -#endif }; /* @@ -4865,7 +4864,7 @@ static int ide_tape_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idetape_driver); + ide_register_subdriver(drive, &idetape_driver); kref_init(&tape->kref); diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index f2b547ff7722..ae5bf2be6f52 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -168,11 +168,12 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ +static int initializing; /* set while initializing built-in drivers */ DECLARE_MUTEX(ide_cfg_sem); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif @@ -215,6 +216,9 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->bus_state = BUSSTATE_ON; hwif->atapi_dma = 0; /* disable all atapi dma */ + hwif->ultra_mask = 0x80; /* disable all ultra */ + hwif->mwdma_mask = 0x80; /* disable all mwdma */ + hwif->swdma_mask = 0x80; /* disable all swdma */ init_completion(&hwif->gendev_rel_comp); @@ -301,7 +305,9 @@ static void __init init_ide_data (void) #endif } #ifdef CONFIG_IDE_ARM + initializing = 1; ide_arm_init(); + initializing = 0; #endif } @@ -347,6 +353,10 @@ static int ide_system_bus_speed(void) return system_bus_speed; } +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_ide_root; +#endif + static struct resource* hwif_request_region(ide_hwif_t *hwif, unsigned long addr, int num) { @@ -470,7 +480,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->tuneproc = tmp_hwif->tuneproc; hwif->speedproc = tmp_hwif->speedproc; - hwif->udma_filter = tmp_hwif->udma_filter; hwif->selectproc = tmp_hwif->selectproc; hwif->reset_poll = tmp_hwif->reset_poll; hwif->pre_reset = tmp_hwif->pre_reset; @@ -590,7 +599,7 @@ void ide_unregister(unsigned int index) spin_unlock_irq(&ide_lock); - ide_proc_unregister_port(hwif); + destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; /* @@ -742,7 +751,6 @@ void ide_setup_ports ( hw_regs_t *hw, /** * ide_register_hw_with_fixup - register IDE interface * @hw: hardware registers - * @initializing: set while initializing built-in drivers * @hwifp: pointer to returned hwif * @fixup: fixup function * @@ -752,9 +760,7 @@ void ide_setup_ports ( hw_regs_t *hw, * Returns -1 on error. */ -int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, - ide_hwif_t **hwifp, - void(*fixup)(ide_hwif_t *hwif)) +int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) { int index, retry = 1; ide_hwif_t *hwif; @@ -795,7 +801,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, if (!initializing) { probe_hwif_init_with_fixup(hwif, fixup); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); } if (hwifp) @@ -806,9 +812,9 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, EXPORT_SYMBOL(ide_register_hw_with_fixup); -int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp) +int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp) { - return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL); + return ide_register_hw_with_fixup(hw, hwifp, NULL); } EXPORT_SYMBOL(ide_register_hw); @@ -819,7 +825,205 @@ EXPORT_SYMBOL(ide_register_hw); DECLARE_MUTEX(ide_setting_sem); -EXPORT_SYMBOL_GPL(ide_setting_sem); +/** + * __ide_add_setting - add an ide setting option + * @drive: drive to use + * @name: setting name + * @rw: true if the function is read write + * @read_ioctl: function to call on read + * @write_ioctl: function to call on write + * @data_type: type of data + * @min: range minimum + * @max: range maximum + * @mul_factor: multiplication scale + * @div_factor: divison scale + * @data: private data field + * @set: setting + * @auto_remove: setting auto removal flag + * + * Removes the setting named from the device if it is present. + * The function takes the settings_lock to protect against + * parallel changes. This function must not be called from IRQ + * context. Returns 0 on success or -1 on failure. + * + * BUGS: This code is seriously over-engineered. There is also + * magic about how the driver specific features are setup. If + * a driver is attached we assume the driver settings are auto + * remove. + */ + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) +{ + ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; + + down(&ide_setting_sem); + while ((*p) && strcmp((*p)->name, name) < 0) + p = &((*p)->next); + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + goto abort; + if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) + goto abort; + strcpy(setting->name, name); + setting->rw = rw; + setting->read_ioctl = read_ioctl; + setting->write_ioctl = write_ioctl; + setting->data_type = data_type; + setting->min = min; + setting->max = max; + setting->mul_factor = mul_factor; + setting->div_factor = div_factor; + setting->data = data; + setting->set = set; + + setting->next = *p; + if (auto_remove) + setting->auto_remove = 1; + *p = setting; + up(&ide_setting_sem); + return 0; +abort: + up(&ide_setting_sem); + kfree(setting); + return -1; +} + +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + +EXPORT_SYMBOL(ide_add_setting); + +/** + * __ide_remove_setting - remove an ide setting option + * @drive: drive to use + * @name: setting name + * + * Removes the setting named from the device if it is present. + * The caller must hold the setting semaphore. + */ + +static void __ide_remove_setting (ide_drive_t *drive, char *name) +{ + ide_settings_t **p, *setting; + + p = (ide_settings_t **) &drive->settings; + + while ((*p) && strcmp((*p)->name, name)) + p = &((*p)->next); + if ((setting = (*p)) == NULL) + return; + + (*p) = setting->next; + + kfree(setting->name); + kfree(setting); +} + +/** + * ide_find_setting_by_ioctl - find a drive specific ioctl + * @drive: drive to scan + * @cmd: ioctl command to handle + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + +static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) +{ + ide_settings_t *setting = drive->settings; + + while (setting) { + if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) + break; + setting = setting->next; + } + + return setting; +} + +/** + * ide_find_setting_by_name - find a drive specific setting + * @drive: drive to scan + * @name: setting name + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + +ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) +{ + ide_settings_t *setting = drive->settings; + + while (setting) { + if (strcmp(setting->name, name) == 0) + break; + setting = setting->next; + } + return setting; +} + +/** + * auto_remove_settings - remove driver specific settings + * @drive: drive + * + * Automatically remove all the driver specific settings for this + * drive. This function may not be called from IRQ context. The + * caller must hold ide_setting_sem. + */ + +static void auto_remove_settings (ide_drive_t *drive) +{ + ide_settings_t *setting; +repeat: + setting = drive->settings; + while (setting) { + if (setting->auto_remove) { + __ide_remove_setting(drive, setting->name); + goto repeat; + } + setting = setting->next; + } +} + +/** + * ide_read_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * + * Read a drive setting and return the value. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + */ + +int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) +{ + int val = -EINVAL; + unsigned long flags; + + if ((setting->rw & SETTING_READ)) { + spin_lock_irqsave(&ide_lock, flags); + switch(setting->data_type) { + case TYPE_BYTE: + val = *((u8 *) setting->data); + break; + case TYPE_SHORT: + val = *((u16 *) setting->data); + break; + case TYPE_INT: + case TYPE_INTA: + val = *((u32 *) setting->data); + break; + } + spin_unlock_irqrestore(&ide_lock, flags); + } + return val; +} /** * ide_spin_wait_hwgroup - wait for group @@ -854,14 +1058,61 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive) EXPORT_SYMBOL(ide_spin_wait_hwgroup); -int set_io_32bit(ide_drive_t *drive, int arg) +/** + * ide_write_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * @val: value + * + * Write a drive setting if it is possible. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + * + * FIXME: This should be changed to enqueue a special request + * to the driver to change settings, and then wait on a sema for completion. + * The current scheme of polling is kludgy, though safe enough. + */ + +int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { - if (drive->no_io_32bit) - return -EPERM; + int i; + u32 *p; - if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (!(setting->rw & SETTING_WRITE)) + return -EPERM; + if (val < setting->min || val > setting->max) return -EINVAL; + if (setting->set) + return setting->set(drive, val); + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + switch (setting->data_type) { + case TYPE_BYTE: + *((u8 *) setting->data) = val; + break; + case TYPE_SHORT: + *((u16 *) setting->data) = val; + break; + case TYPE_INT: + *((u32 *) setting->data) = val; + break; + case TYPE_INTA: + p = (u32 *) setting->data; + for (i = 0; i < 1 << PARTN_BITS; i++, p++) + *p = val; + break; + } + spin_unlock_irq(&ide_lock); + return 0; +} +static int set_io_32bit(ide_drive_t *drive, int arg) +{ drive->io_32bit = arg; #ifdef CONFIG_BLK_DEV_DTC2278 if (HWIF(drive)->chipset == ide_dtc2278) @@ -870,28 +1121,12 @@ int set_io_32bit(ide_drive_t *drive, int arg) return 0; } -static int set_ksettings(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->keep_settings = arg; - spin_unlock_irq(&ide_lock); - - return 0; -} - -int set_using_dma(ide_drive_t *drive, int arg) +static int set_using_dma (ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; int err = -EPERM; - if (arg < 0 || arg > 1) - return -EINVAL; - if (!drive->id || !(drive->id->capability & 1)) goto out; @@ -924,20 +1159,14 @@ int set_using_dma(ide_drive_t *drive, int arg) out: return err; #else - if (arg < 0 || arg > 1) - return -EINVAL; - return -EPERM; #endif } -int set_pio_mode(ide_drive_t *drive, int arg) +static int set_pio_mode (ide_drive_t *drive, int arg) { struct request rq; - if (arg < 0 || arg > 255) - return -EINVAL; - if (!HWIF(drive)->tuneproc) return -ENOSYS; if (drive->special.b.set_tune) @@ -949,20 +1178,42 @@ int set_pio_mode(ide_drive_t *drive, int arg) return 0; } -static int set_unmaskirq(ide_drive_t *drive, int arg) +static int set_xfer_rate (ide_drive_t *drive, int arg) { - if (drive->no_unmask) - return -EPERM; + int err = ide_wait_cmd(drive, + WIN_SETFEATURES, (u8) arg, + SETFEATURES_XFER, 0, NULL); - if (arg < 0 || arg > 1) - return -EINVAL; + if (!err && arg) { + ide_set_xfer_rate(drive, (u8) arg); + ide_driveid_update(drive); + } + return err; +} - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->unmask = arg; - spin_unlock_irq(&ide_lock); +/** + * ide_add_generic_settings - generic ide settings + * @drive: drive being configured + * + * Add the generic parts of the system settings to the /proc files and + * ioctls for this IDE device. The caller must not be holding the + * ide_setting_sem. + */ - return 0; +void ide_add_generic_settings (ide_drive_t *drive) +{ +/* + * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + */ + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } /** @@ -1034,23 +1285,27 @@ static int generic_ide_resume(struct device *dev) int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - unsigned long flags; + ide_settings_t *setting; ide_driver_t *drv; + int err = 0; void __user *p = (void __user *)arg; - int err = 0, (*setfunc)(ide_drive_t *, int); - u8 *val; - switch (cmd) { - case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; - case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; - case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; - case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; - case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; - case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; - case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; - case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; - case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; + down(&ide_setting_sem); + if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { + if (cmd == setting->read_ioctl) { + err = ide_read_setting(drive, setting); + up(&ide_setting_sem); + return err >= 0 ? put_user(err, (long __user *)arg) : err; + } else { + if (bdev != bdev->bd_contains) + err = -EINVAL; + else + err = ide_write_setting(drive, setting, arg); + up(&ide_setting_sem); + return err; + } } + up(&ide_setting_sem); switch (cmd) { case HDIO_OBSOLETE_IDENTITY: @@ -1104,7 +1359,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_init_hwif_ports(&hw, (unsigned long) args[0], (unsigned long) args[1], NULL); hw.irq = args[2]; - if (ide_register_hw(&hw, 0, NULL) == -1) + if (ide_register_hw(&hw, NULL) == -1) return -EIO; return 0; } @@ -1179,28 +1434,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device default: return -EINVAL; } - -read_val: - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - err = *val; - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - down(&ide_setting_sem); - err = setfunc(drive, arg); - up(&ide_setting_sem); - } - } - return err; } EXPORT_SYMBOL(generic_ide_ioctl); @@ -1333,13 +1566,13 @@ static int __init ide_setup(char *s) return 1; } -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI if (!strcmp(s, "ide=reverse")) { ide_scan_direction = 1; printk(" : Enabled support for IDE inverse scan order.\n"); return 1; } -#endif +#endif /* CONFIG_BLK_DEV_IDEPCI */ #ifdef CONFIG_BLK_DEV_IDEACPI if (!strcmp(s, "ide=noacpi")) { @@ -1599,9 +1832,9 @@ extern void __init h8300_ide_init(void); */ static void __init probe_for_hwifs (void) { -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI ide_scan_pcibus(ide_scan_direction); -#endif +#endif /* CONFIG_BLK_DEV_IDEPCI */ #ifdef CONFIG_ETRAX_IDE { @@ -1659,6 +1892,54 @@ static void __init probe_for_hwifs (void) #endif } +void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) +{ +#ifdef CONFIG_PROC_FS + ide_add_proc_entries(drive->proc, driver->proc, drive); +#endif +} + +EXPORT_SYMBOL(ide_register_subdriver); + +/** + * ide_unregister_subdriver - disconnect drive from driver + * @drive: drive to unplug + * @driver: driver + * + * Disconnect a drive from the driver it was attached to and then + * clean up the various proc files and other objects attached to it. + * + * Takes ide_setting_sem and ide_lock. + * Caller must hold none of the locks. + */ + +void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) +{ + unsigned long flags; + +#ifdef CONFIG_PROC_FS + ide_remove_proc_entries(drive->proc, driver->proc); +#endif + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + /* + * ide_setting_sem protects the settings list + * ide_lock protects the use of settings + * + * so we need to hold both, ide_settings_sem because we want to + * modify the settings list, and ide_lock because we cannot take + * a setting out that is being used. + * + * OTOH both ide_{read,write}_setting are only ever used under + * ide_setting_sem. + */ + auto_remove_settings(drive); + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); +} + +EXPORT_SYMBOL(ide_unregister_subdriver); + /* * Probe module */ @@ -1790,7 +2071,9 @@ static int __init ide_init(void) init_ide_data(); - proc_ide_create(); +#ifdef CONFIG_PROC_FS + proc_ide_root = proc_mkdir("ide", NULL); +#endif #ifdef CONFIG_BLK_DEV_ALI14XX if (probe_ali14xx) @@ -1813,9 +2096,14 @@ static int __init ide_init(void) (void)qd65xx_init(); #endif + initializing = 1; /* Probe for special PCI and other "known" interface chipsets. */ probe_for_hwifs(); + initializing = 0; +#ifdef CONFIG_PROC_FS + proc_ide_create(); +#endif return 0; } @@ -1855,7 +2143,9 @@ void __exit cleanup_module (void) pnpide_exit(); #endif +#ifdef CONFIG_PROC_FS proc_ide_destroy(); +#endif bus_unregister(&ide_bus_type); } diff --git a/trunk/drivers/ide/legacy/ali14xx.c b/trunk/drivers/ide/legacy/ali14xx.c index df17ed68c0bc..91961aa03047 100644 --- a/trunk/drivers/ide/legacy/ali14xx.c +++ b/trunk/drivers/ide/legacy/ali14xx.c @@ -223,8 +223,7 @@ static int __init ali14xx_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/legacy/buddha.c b/trunk/drivers/ide/legacy/buddha.c index 101aee1711c4..1ed224a01f79 100644 --- a/trunk/drivers/ide/legacy/buddha.c +++ b/trunk/drivers/ide/legacy/buddha.c @@ -213,7 +213,7 @@ void __init buddha_init(void) IRQ_AMIGA_PORTS); } - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { hwif->mmio = 1; printk("ide%d: ", index); diff --git a/trunk/drivers/ide/legacy/dtc2278.c b/trunk/drivers/ide/legacy/dtc2278.c index 36a3f0ac6162..0219ffa64db6 100644 --- a/trunk/drivers/ide/legacy/dtc2278.c +++ b/trunk/drivers/ide/legacy/dtc2278.c @@ -138,8 +138,7 @@ static int __init dtc2278_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/legacy/falconide.c b/trunk/drivers/ide/legacy/falconide.c index e1e9d9d6893f..a9f2cd5bb81e 100644 --- a/trunk/drivers/ide/legacy/falconide.c +++ b/trunk/drivers/ide/legacy/falconide.c @@ -70,7 +70,7 @@ void __init falconide_init(void) 0, 0, NULL, // falconide_iops, IRQ_MFP_IDE); - index = ide_register_hw(&hw, 1, NULL); + index = ide_register_hw(&hw, NULL); if (index != -1) printk("ide%d: Falcon IDE interface\n", index); diff --git a/trunk/drivers/ide/legacy/gayle.c b/trunk/drivers/ide/legacy/gayle.c index 0830a021bbb6..dcfadbbf55d8 100644 --- a/trunk/drivers/ide/legacy/gayle.c +++ b/trunk/drivers/ide/legacy/gayle.c @@ -165,7 +165,7 @@ void __init gayle_init(void) // &gayle_iops, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { hwif->mmio = 1; switch (i) { diff --git a/trunk/drivers/ide/legacy/ht6560b.c b/trunk/drivers/ide/legacy/ht6560b.c index c8f353b1296f..a2832643c522 100644 --- a/trunk/drivers/ide/legacy/ht6560b.c +++ b/trunk/drivers/ide/legacy/ht6560b.c @@ -357,8 +357,7 @@ int __init ht6560b_init(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index 2f3977f195b7..c6522a64d7ec 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -153,7 +153,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave); + return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); } /*====================================================================== diff --git a/trunk/drivers/ide/legacy/macide.c b/trunk/drivers/ide/legacy/macide.c index c211fc78345d..4c0079ad52ac 100644 --- a/trunk/drivers/ide/legacy/macide.c +++ b/trunk/drivers/ide/legacy/macide.c @@ -102,21 +102,21 @@ void macide_init(void) 0, 0, macide_ack_intr, // quadra_ide_iops, IRQ_NUBUS_F); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); break; case MAC_IDE_PB: ide_setup_ports(&hw, IDE_BASE, macide_offsets, 0, 0, macide_ack_intr, // macide_pb_iops, IRQ_NUBUS_C); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); break; case MAC_IDE_BABOON: ide_setup_ports(&hw, BABOON_BASE, macide_offsets, 0, 0, NULL, // macide_baboon_iops, IRQ_BABOON_1); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index == -1) break; if (macintosh_config->ident == MAC_MODEL_PB190) { diff --git a/trunk/drivers/ide/legacy/q40ide.c b/trunk/drivers/ide/legacy/q40ide.c index e628a983ce33..74f08124eabb 100644 --- a/trunk/drivers/ide/legacy/q40ide.c +++ b/trunk/drivers/ide/legacy/q40ide.c @@ -142,7 +142,7 @@ void q40ide_init(void) 0, NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); // **FIXME** if (index != -1) hwif->mmio = 1; diff --git a/trunk/drivers/ide/legacy/qd65xx.c b/trunk/drivers/ide/legacy/qd65xx.c index d1414a75b523..2fb8f50f1293 100644 --- a/trunk/drivers/ide/legacy/qd65xx.c +++ b/trunk/drivers/ide/legacy/qd65xx.c @@ -427,7 +427,7 @@ static int __init qd_probe(int base) qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 1; } @@ -459,7 +459,7 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 1; } else { @@ -479,8 +479,7 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; /* no other qd65xx possible */ } diff --git a/trunk/drivers/ide/legacy/umc8672.c b/trunk/drivers/ide/legacy/umc8672.c index ddc403a0bd82..ca7974455578 100644 --- a/trunk/drivers/ide/legacy/umc8672.c +++ b/trunk/drivers/ide/legacy/umc8672.c @@ -160,8 +160,7 @@ static int __init umc8672_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/mips/au1xxx-ide.c b/trunk/drivers/ide/mips/au1xxx-ide.c index ca95e990862e..d54d9fe92a7d 100644 --- a/trunk/drivers/ide/mips/au1xxx-ide.c +++ b/trunk/drivers/ide/mips/au1xxx-ide.c @@ -760,9 +760,6 @@ static int au_ide_probe(struct device *dev) #endif probe_hwif_init(hwif); - - ide_proc_register_port(hwif); - dev_set_drvdata(dev, hwif); printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); diff --git a/trunk/drivers/ide/mips/swarm.c b/trunk/drivers/ide/mips/swarm.c index 6e935d7c63fd..81fa06851b27 100644 --- a/trunk/drivers/ide/mips/swarm.c +++ b/trunk/drivers/ide/mips/swarm.c @@ -129,9 +129,6 @@ static int __devinit swarm_ide_probe(struct device *dev) hwif->irq = hwif->hw.irq; probe_hwif_init(hwif); - - ide_proc_register_port(hwif); - dev_set_drvdata(dev, hwif); return 0; diff --git a/trunk/drivers/ide/pci/aec62xx.c b/trunk/drivers/ide/pci/aec62xx.c index b173bc66ce1e..73bdf64dbbfc 100644 --- a/trunk/drivers/ide/pci/aec62xx.c +++ b/trunk/drivers/ide/pci/aec62xx.c @@ -87,12 +87,38 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr return chipset_table->ultra_settings; } +static u8 aec62xx_ratemask (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 mode; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + mode = (inb(hwif->channel ? + hwif->mate->dma_status : + hwif->dma_status) & 0x10) ? 4 : 3; + break; + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + mode = 2; + break; + case PCI_DEVICE_ID_ARTOP_ATP850UF: + default: + return 1; + } + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u16 d_conf = 0; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); u8 ultra = 0, ultra_conf = 0; u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; unsigned long flags; @@ -119,7 +145,7 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); u8 unit = (drive->select.b.unit & 0x01); u8 tmp1 = 0, tmp2 = 0; u8 ultra = 0, drive_conf = 0, ultra_conf = 0; @@ -155,6 +181,17 @@ static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed) } } +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) aec62xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -163,7 +200,7 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -224,13 +261,11 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - hwif->autodma = 0; hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) + if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) hwif->serialized = hwif->channel; if (hwif->mate) @@ -242,15 +277,7 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) return; } - hwif->ultra_mask = hwif->cds->udma_mask; - - /* atp865 and atp865r */ - if (hwif->ultra_mask == 0x3f) { - /* check bit 0x10 of DMA status register */ - if (inb(pci_resource_start(dev, 4) + 2) & 0x10) - hwif->ultra_mask = 0x7f; /* udma0-6 */ - } - + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; @@ -317,7 +344,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "AEC6260", .init_setup = init_setup_aec62xx, @@ -327,7 +353,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = NOAUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "AEC6260R", .init_setup = init_setup_aec62xx, @@ -338,7 +363,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = NEVER_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "AEC6X80", .init_setup = init_setup_aec6x80, @@ -348,7 +372,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "AEC6X80R", .init_setup = init_setup_aec6x80, @@ -359,7 +382,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c index 428efdae0c7b..946a12746cb5 100644 --- a/trunk/drivers/ide/pci/alim15x3.c +++ b/trunk/drivers/ide/pci/alim15x3.c @@ -50,7 +50,7 @@ static u8 m5229_revision; static u8 chip_is_1543c_e; static struct pci_dev *isa_dev; -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -278,7 +278,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ /** * ali15x3_tune_pio - set up chipset for PIO mode @@ -378,31 +378,74 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) } /** - * ali_udma_filter - compute UDMA mask - * @drive: IDE device + * ali15x3_can_ultra - check for ultra DMA support + * @drive: drive to do the check * - * Return available UDMA modes. - * - * The actual rules for the ALi are: + * Check the drive and controller revisions. Return 0 if UDMA is + * not available, or 1 if UDMA can be used. The actual rules for + * the ALi are * No UDMA on revisions <= 0x20 * Disk only for revisions < 0xC2 * Not WDC drives for revisions < 0xC2 * * FIXME: WDC ifdef needs to die */ - -static u8 ali_udma_filter(ide_drive_t *drive) + +static u8 ali15x3_can_ultra (ide_drive_t *drive) { - if (m5229_revision > 0x20 && m5229_revision < 0xC2) { - if (drive->media != ide_disk) - return 0; #ifndef CONFIG_WDC_ALI15X3 - if (chip_is_1543c_e && strstr(drive->id->model, "WDC ")) - return 0; -#endif + struct hd_driveid *id = drive->id; +#endif /* CONFIG_WDC_ALI15X3 */ + + if (m5229_revision <= 0x20) { + return 0; + } else if ((m5229_revision < 0xC2) && +#ifndef CONFIG_WDC_ALI15X3 + ((chip_is_1543c_e && strstr(id->model, "WDC ")) || + (drive->media!=ide_disk))) { +#else /* CONFIG_WDC_ALI15X3 */ + (drive->media!=ide_disk)) { +#endif /* CONFIG_WDC_ALI15X3 */ + return 0; + } else { + return 1; + } +} + +/** + * ali15x3_ratemask - generate DMA mode list + * @drive: drive to compute against + * + * Generate a list of the available DMA modes for the drive. + * FIXME: this function contains lots of bogus masking we can dump + * + * Return the highest available mode (UDMA33, UDMA66, UDMA100,..) + */ + +static u8 ali15x3_ratemask (ide_drive_t *drive) +{ + u8 mode = 0, can_ultra = ali15x3_can_ultra(drive); + + if (m5229_revision > 0xC4 && can_ultra) { + mode = 4; + } else if (m5229_revision == 0xC4 && can_ultra) { + mode = 3; + } else if (m5229_revision >= 0xC2 && can_ultra) { + mode = 2; + } else if (can_ultra) { + return 1; + } else { + return 0; } - return drive->hwif->ultra_mask; + /* + * If the drive sees no suitable cable then UDMA 33 + * is the highest permitted mode + */ + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; } /** @@ -418,7 +461,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); u8 speed1 = speed; u8 unit = (drive->select.b.unit & 0x01); u8 tmpbyte = 0x00; @@ -468,7 +511,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, ali15x3_ratemask(drive)); if (!(speed)) return 0; @@ -566,13 +609,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) if (!ali_proc) { ali_proc = 1; bmide_dev = dev; ide_pci_create_host_proc("ali", ali_get_info); } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ local_irq_save(flags); @@ -728,7 +771,6 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->autodma = 0; hwif->tuneproc = &ali15x3_tune_drive; hwif->speedproc = &ali15x3_tune_chipset; - hwif->udma_filter = &ali_udma_filter; /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0; @@ -741,17 +783,8 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->atapi_dma = 1; - if (m5229_revision <= 0x20) - hwif->ultra_mask = 0x00; /* no udma */ - else if (m5229_revision < 0xC2) - hwif->ultra_mask = 0x07; /* udma0-2 */ - else if (m5229_revision == 0xC2 || m5229_revision == 0xC3) - hwif->ultra_mask = 0x1f; /* udma0-4 */ - else if (m5229_revision == 0xC4) - hwif->ultra_mask = 0x3f; /* udma0-5 */ - else - hwif->ultra_mask = 0x7f; /* udma0-6 */ - + if (m5229_revision > 0x20) + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/trunk/drivers/ide/pci/amd74xx.c b/trunk/drivers/ide/pci/amd74xx.c index becb1a5648b0..7989bdd842a2 100644 --- a/trunk/drivers/ide/pci/amd74xx.c +++ b/trunk/drivers/ide/pci/amd74xx.c @@ -92,7 +92,7 @@ static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3 * AMD /proc entry. */ -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS #include #include @@ -402,14 +402,14 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch * Register /proc/ide/amd74xx entry */ -#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) if (!amd74xx_proc) { amd_base = pci_resource_start(dev, 4); bmide_dev = dev; ide_pci_create_host_proc("amd74xx", amd74xx_get_info); amd74xx_proc = 1; } -#endif /* DISPLAY_AMD_TIMINGS && CONFIG_IDE_PROC_FS */ +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ return dev->irq; } diff --git a/trunk/drivers/ide/pci/atiixp.c b/trunk/drivers/ide/pci/atiixp.c index 0e52ad722a72..2d48af32e3f4 100644 --- a/trunk/drivers/ide/pci/atiixp.c +++ b/trunk/drivers/ide/pci/atiixp.c @@ -48,6 +48,22 @@ static int save_mdma_mode[4]; static DEFINE_SPINLOCK(atiixp_lock); +/** + * atiixp_ratemask - compute rate mask for ATIIXP IDE + * @drive: IDE drive to compute for + * + * Returns the available modes for the ATIIXP IDE controller. + */ + +static u8 atiixp_ratemask(ide_drive_t *drive) +{ + u8 mode = 3; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * atiixp_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -173,7 +189,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) u16 tmp16; u8 speed, pio; - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed); spin_lock_irqsave(&atiixp_lock, flags); @@ -206,6 +222,26 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/** + * atiixp_config_drive_for_dma - configure drive for DMA + * @drive: IDE drive to configure + * + * Set up a ATIIXP interface channel for the best available speed. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. + */ + +static int atiixp_config_drive_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive)); + + if (!speed) + return 0; + + (void) atiixp_speedproc(drive, speed); + return ide_dma_enable(drive); +} + /** * atiixp_dma_check - set up an IDE device * @drive: IDE drive to configure @@ -220,7 +256,7 @@ static int atiixp_dma_check(ide_drive_t *drive) drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/trunk/drivers/ide/pci/cmd64x.c b/trunk/drivers/ide/pci/cmd64x.c index 61ea96b5555c..77f51ab6d439 100644 --- a/trunk/drivers/ide/pci/cmd64x.c +++ b/trunk/drivers/ide/pci/cmd64x.c @@ -74,7 +74,7 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -165,7 +165,7 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ static u8 quantize_timing(int timing, int quant) { @@ -292,6 +292,55 @@ static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio) (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); } +static u8 cmd64x_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode = 0; + + switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: + mode = 3; + break; + case PCI_DEVICE_ID_CMD_648: + mode = 2; + break; + case PCI_DEVICE_ID_CMD_643: + return 0; + + case PCI_DEVICE_ID_CMD_646: + { + unsigned int class_rev = 0; + pci_read_config_dword(dev, + PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ + switch(class_rev) { + case 0x07: + case 0x05: + return 1; + case 0x03: + case 0x01: + default: + return 0; + } + } + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); @@ -299,7 +348,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) u8 unit = drive->dn & 0x01; u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(cmd64x_ratemask(drive), speed); if (speed >= XFER_SW_DMA_0) { (void) pci_read_config_byte(dev, pciU, ®U); @@ -354,7 +403,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); if (!speed) return 0; @@ -548,7 +597,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) cmd_devs[n_cmd_devs++] = dev; @@ -556,7 +605,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha cmd64x_proc = 1; ide_pci_create_host_proc("cmd64x", cmd64x_get_info); } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */ +#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0; } @@ -595,25 +644,16 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->atapi_dma = 1; - hwif->ultra_mask = hwif->cds->udma_mask; - - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5) - hwif->ultra_mask = 0x00; - + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; + if (dev->device == PCI_DEVICE_ID_CMD_643) + hwif->ultra_mask = 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_646) + hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_648) + hwif->ultra_mask = 0x1f; + hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_cmd64x(hwif); @@ -676,7 +716,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x00, /* no udma */ },{ /* 1 */ .name = "CMD646", .init_setup = init_setup_cmd646, @@ -686,7 +725,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 2 */ .name = "CMD648", .init_setup = init_setup_cmd64x, @@ -696,7 +734,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "CMD649", .init_setup = init_setup_cmd64x, @@ -706,7 +743,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/cs5520.c b/trunk/drivers/ide/pci/cs5520.c index 3b88a3a56116..400859a839f7 100644 --- a/trunk/drivers/ide/pci/cs5520.c +++ b/trunk/drivers/ide/pci/cs5520.c @@ -213,7 +213,6 @@ static ide_pci_device_t cyrix_chipsets[] __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index; ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; @@ -240,21 +239,10 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, 14, &index); - if ((index.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index.b.low]; - if ((index.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index.b.high]; - - if (hwif) - probe_hwif_init(hwif); - if (mate) - probe_hwif_init(mate); - - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); - + if((index.b.low & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.low]); + if((index.b.high & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.high]); return 0; } diff --git a/trunk/drivers/ide/pci/cs5535.c b/trunk/drivers/ide/pci/cs5535.c index 41925c47ef05..45f43efbf92c 100644 --- a/trunk/drivers/ide/pci/cs5535.c +++ b/trunk/drivers/ide/pci/cs5535.c @@ -127,6 +127,20 @@ static void cs5535_set_speed(ide_drive_t *drive, u8 speed) } } +static u8 cs5535_ratemask(ide_drive_t *drive) +{ + /* eighty93 will return 1 if it's 80core and capable of + exceeding udma2, 0 otherwise. we need ratemask to set + the max speed and if we can > udma2 then we return 2 + which selects speed_max as udma4 which is the 5535's max + speed, and 1 selects udma2 which is the max for 40c */ + if (!eighty_ninty_three(drive)) + return 1; + + return 2; +} + + /**** * cs5535_set_drive - Configure the drive to the new speed * @drive: Drive to set up @@ -137,7 +151,7 @@ static void cs5535_set_speed(ide_drive_t *drive, u8 speed) */ static int cs5535_set_drive(ide_drive_t *drive, u8 speed) { - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(cs5535_ratemask(drive), speed); ide_config_drive_speed(drive, speed); cs5535_set_speed(drive, speed); @@ -164,13 +178,28 @@ static void cs5535_tuneproc(ide_drive_t *drive, u8 xferspeed) cs5535_set_speed(drive, xferspeed); } +static int cs5535_config_drive_for_dma(ide_drive_t *drive) +{ + u8 speed; + + speed = ide_dma_speed(drive, cs5535_ratemask(drive)); + + /* If no DMA speed was available then let dma_check hit pio */ + if (!speed) { + return 0; + } + + cs5535_set_drive(drive, speed); + return ide_dma_enable(drive); +} + static int cs5535_dma_check(ide_drive_t *drive) { u8 speed; drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/trunk/drivers/ide/pci/delkin_cb.c b/trunk/drivers/ide/pci/delkin_cb.c index 46f4a888c037..dd7ec37fdeab 100644 --- a/trunk/drivers/ide/pci/delkin_cb.c +++ b/trunk/drivers/ide/pci/delkin_cb.c @@ -80,7 +80,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_register_hw_with_fixup(&hw, 0, &hwif, ide_undecoded_slave); + rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); if (rc < 0) { printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); pci_disable_device(dev); diff --git a/trunk/drivers/ide/pci/hpt34x.c b/trunk/drivers/ide/pci/hpt34x.c index 2c24c3de8846..924eaa3a5708 100644 --- a/trunk/drivers/ide/pci/hpt34x.c +++ b/trunk/drivers/ide/pci/hpt34x.c @@ -43,10 +43,15 @@ #define HPT343_DEBUG_DRIVE_INFO 0 +static u8 hpt34x_ratemask (ide_drive_t *drive) +{ + return 1; +} + static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(hpt34x_ratemask(drive), xferspeed); u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; u8 hi_speed, lo_speed; @@ -84,11 +89,29 @@ static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initially for designed for + * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) hpt34x_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) #ifndef CONFIG_HPT34X_AUTODMA return -1; #else diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index fcbc5605b38e..cf9d344d19f8 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -514,31 +514,43 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) return 0; } +static u8 hpt3xx_ratemask(ide_drive_t *drive) +{ + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); + u8 mode = info->max_mode; + + if (!eighty_ninty_three(drive) && mode) + mode = min(mode, (u8)1); + return mode; +} + /* * Note for the future; the SATA hpt37x we must set * either PIO or UDMA modes 0,4,5 */ - -static u8 hpt3xx_udma_filter(ide_drive_t *drive) + +static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) { struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); u8 chip_type = info->chip_type; - u8 mode = info->max_mode; - u8 mask; + u8 mode = hpt3xx_ratemask(drive); + + if (drive->media != ide_disk) + return min(speed, (u8)XFER_PIO_4); switch (mode) { case 0x04: - mask = 0x7f; + speed = min_t(u8, speed, XFER_UDMA_6); break; case 0x03: - mask = 0x3f; + speed = min_t(u8, speed, XFER_UDMA_5); if (chip_type >= HPT374) break; if (!check_in_drive_list(drive, bad_ata100_5)) goto check_bad_ata33; /* fall thru */ case 0x02: - mask = 0x1f; + speed = min_t(u8, speed, XFER_UDMA_4); /* * CHECK ME, Does this need to be changed to HPT374 ?? @@ -549,13 +561,13 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) !check_in_drive_list(drive, bad_ata66_4)) goto check_bad_ata33; - mask = 0x0f; + speed = min_t(u8, speed, XFER_UDMA_3); if (HPT366_ALLOW_ATA66_3 && !check_in_drive_list(drive, bad_ata66_3)) goto check_bad_ata33; /* fall thru */ case 0x01: - mask = 0x07; + speed = min_t(u8, speed, XFER_UDMA_2); check_bad_ata33: if (chip_type >= HPT370A) @@ -565,10 +577,10 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) /* fall thru */ case 0x00: default: - mask = 0x00; + speed = min_t(u8, speed, XFER_MW_DMA_2); break; } - return mask; + return speed; } static u32 get_speed_setting(u8 speed, struct hpt_info *info) @@ -596,19 +608,12 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = drive->dn ? 0x44 : 0x40; + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : + (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; - u32 itr_mask, new_itr; - - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - - itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : - (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); - - new_itr = get_speed_setting(speed, info); /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) @@ -628,19 +633,12 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = 0x40 + (drive->dn * 4); + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : + (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; - u32 itr_mask, new_itr; - - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - - itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : - (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); - - new_itr = get_speed_setting(speed, info); pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); @@ -669,6 +667,24 @@ static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); } +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initially designed for + * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. + * + */ +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); + + if (!speed) + return 0; + + (void) hpt3xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int hpt3xx_quirkproc(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -723,7 +739,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -1255,7 +1271,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; hwif->busproc = &hpt3xx_busproc; - hwif->udma_filter = &hpt3xx_udma_filter; /* * HPT3xxN chips have some complications: diff --git a/trunk/drivers/ide/pci/it8213.c b/trunk/drivers/ide/pci/it8213.c index c04a02687b95..424f00bb160d 100644 --- a/trunk/drivers/ide/pci/it8213.c +++ b/trunk/drivers/ide/pci/it8213.c @@ -17,6 +17,22 @@ #include +/* + * it8213_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 it8213_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + /** * it8213_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -129,7 +145,7 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -197,6 +213,25 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/* + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by the IDE layer when it wants the timings set up. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + + if (!speed) + return 0; + + it8213_tune_chipset(drive, speed); + + return ide_dma_enable(drive); +} + /** * it8213_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -211,7 +246,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive) { u8 pio; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; pio = ide_get_best_pio_mode(drive, 255, 4, NULL); diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c index 442f658c6ae7..4e1254813ee0 100644 --- a/trunk/drivers/ide/pci/it821x.c +++ b/trunk/drivers/ide/pci/it821x.c @@ -228,6 +228,22 @@ static void it821x_clock_strategy(ide_drive_t *drive) } } +/** + * it821x_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 it821x_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * it821x_tunepio - tune a drive * @drive: drive to tune @@ -422,7 +438,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = drive->hwif; struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); switch (speed) { case XFER_PIO_4: @@ -472,7 +488,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); if (speed == 0) return 0; diff --git a/trunk/drivers/ide/pci/jmicron.c b/trunk/drivers/ide/pci/jmicron.c index 76ed25147229..be4fc96c29e0 100644 --- a/trunk/drivers/ide/pci/jmicron.c +++ b/trunk/drivers/ide/pci/jmicron.c @@ -21,6 +21,22 @@ typedef enum { PORT_SATA = 2, } port_type; +/** + * jmicron_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 jmicron_ratemask(ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * ata66_jmicron - Cable check * @hwif: IDE port @@ -113,11 +129,31 @@ static void config_jmicron_chipset_for_pio (ide_drive_t *drive, byte set_speed) static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) { - u8 speed = ide_rate_filter(drive, xferspeed); + + u8 speed = ide_rate_filter(jmicron_ratemask(drive), xferspeed); return ide_config_drive_speed(drive, speed); } +/** + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * As the JMicron snoops for timings all we actually need to do is + * make sure we don't set an invalid mode. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, jmicron_ratemask(drive)); + + if (!speed) + return 0; + + jmicron_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + /** * jmicron_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -128,7 +164,7 @@ static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) static int jmicron_config_drive_for_dma (ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; config_jmicron_chipset_for_pio(drive, 1); diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 65b1e124edf7..2cdd629c653d 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -37,6 +37,8 @@ #include #endif +#define PDC202_DEBUG_CABLE 0 + #undef DEBUG #ifdef DEBUG @@ -80,6 +82,16 @@ static u8 max_dma_rate(struct pci_dev *pdev) return mode; } +static u8 pdcnew_ratemask(ide_drive_t *drive) +{ + u8 mode = max_dma_rate(HWIF(drive)->pci_dev); + + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + + return mode; +} + /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -152,7 +164,7 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) u8 adj = (drive->dn & 1) ? 0x08 : 0x00; int err; - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(pdcnew_ratemask(drive), speed); /* * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will @@ -232,8 +244,17 @@ static int config_chipset_for_dma(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); + u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; + u8 cable = pdcnew_cable_detect(hwif); u8 speed; + if (ultra_66 && cable) { + printk(KERN_WARNING "Warning: %s channel " + "requires an 80-pin cable for operation.\n", + hwif->channel ? "Secondary" : "Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } + if (id->capability & 4) { /* * Set IORDY_EN & PREFETCH_EN (this seems to have @@ -246,7 +267,7 @@ static int config_chipset_for_dma(ide_drive_t *drive) set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); } - speed = ide_max_dma_mode(drive); + speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); if (!speed) return 0; @@ -522,8 +543,7 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; hwif->atapi_dma = 1; - - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->err_stops_fifo = 1; @@ -536,6 +556,11 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ } static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d) @@ -594,7 +619,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 1 */ .name = "PDC20269", .init_setup = init_setup_pdcnew, @@ -603,7 +627,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 2 */ .name = "PDC20270", .init_setup = init_setup_pdc20270, @@ -612,7 +635,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 3 */ .name = "PDC20271", .init_setup = init_setup_pdcnew, @@ -621,7 +643,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 4 */ .name = "PDC20275", .init_setup = init_setup_pdcnew, @@ -630,7 +651,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 5 */ .name = "PDC20276", .init_setup = init_setup_pdc20276, @@ -639,7 +659,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 6 */ .name = "PDC20277", .init_setup = init_setup_pdcnew, @@ -648,7 +667,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ } }; diff --git a/trunk/drivers/ide/pci/pdc202xx_old.c b/trunk/drivers/ide/pci/pdc202xx_old.c index 7146fe3f6ba7..a7a639fe1eaf 100644 --- a/trunk/drivers/ide/pci/pdc202xx_old.c +++ b/trunk/drivers/ide/pci/pdc202xx_old.c @@ -46,6 +46,7 @@ #include #include +#define PDC202_DEBUG_CABLE 0 #define PDC202XX_DEBUG_DRIVE_INFO 0 static const char *pdc_quirk_drives[] = { @@ -100,12 +101,35 @@ static const char *pdc_quirk_drives[] = { #define MC1 0x02 /* DMA"C" timing */ #define MC0 0x01 /* DMA"C" timing */ +static u8 pdc202xx_ratemask (ide_drive_t *drive) +{ + u8 mode; + + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + mode = 3; + break; + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + mode = 2; + break; + case PCI_DEVICE_ID_PROMISE_20246: + return 1; + default: + return 0; + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 drive_pci = 0x60 + (drive->dn << 2); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(pdc202xx_ratemask(drive), xferspeed); u32 drive_conf; u8 AP, BP, CP, DP; @@ -237,7 +261,20 @@ static int config_chipset_for_dma (ide_drive_t *drive) u32 drive_conf = 0; u8 drive_pci = 0x60 + (drive->dn << 2); u8 test1 = 0, test2 = 0, speed = -1; - u8 AP = 0; + u8 AP = 0, cable = 0; + + u8 ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + cable = pdc202xx_old_cable_detect(hwif); + else + ultra_66 = 0; + + if (ultra_66 && cable) { + printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } if (dev->device != PCI_DEVICE_ID_PROMISE_20246) pdc_old_disable_66MHz_clock(drive->hwif); @@ -271,7 +308,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (drive->media == ide_disk) /* PREFETCH_EN */ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - speed = ide_max_dma_mode(drive); + speed = ide_dma_speed(drive, pdc202xx_ratemask(drive)); if (!(speed)) { /* restore original pci-config space */ @@ -441,7 +478,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; hwif->atapi_dma = 1; @@ -463,6 +500,10 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ } static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) @@ -546,7 +587,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 16, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "PDC20262", .init_setup = init_setup_pdc202ata4, @@ -557,7 +597,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -568,7 +607,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "PDC20265", .init_setup = init_setup_pdc20265, @@ -579,7 +617,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, @@ -590,7 +627,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c index 8b219dd63024..061d300ab8be 100644 --- a/trunk/drivers/ide/pci/piix.c +++ b/trunk/drivers/ide/pci/piix.c @@ -105,6 +105,68 @@ static int no_piix_dma; +/** + * piix_ratemask - compute rate mask for PIIX IDE + * @drive: IDE drive to compute for + * + * Returns the available modes for the PIIX IDE controller. + */ + +static u8 piix_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + mode = 3; + break; + /* UDMA 100 capable */ + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_1: + case PCI_DEVICE_ID_INTEL_82801DB_10: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ICH6_19: + case PCI_DEVICE_ID_INTEL_ICH7_21: + case PCI_DEVICE_ID_INTEL_ESB2_18: + case PCI_DEVICE_ID_INTEL_ICH8_6: + mode = 3; + break; + /* UDMA 66 capable */ + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82372FB_1: + mode = 2; + break; + /* UDMA 33 capable */ + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + return 1; + /* Non UDMA capable (MWDMA2) */ + case PCI_DEVICE_ID_INTEL_82371SB_1: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + default: + return 0; + } + + /* + * If we are UDMA66 capable fall back to UDMA33 + * if the drive cannot see an 80pin cable. + */ + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + /** * piix_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -239,7 +301,7 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -303,6 +365,30 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/** + * piix_config_drive_for_dma - configure drive for DMA + * @drive: IDE drive to configure + * + * Set up a PIIX interface channel for the best available speed. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. + */ + +static int piix_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); + + /* + * If no DMA speed was available or the chipset has DMA bugs + * then disable DMA and use PIO + */ + if (!speed) + return 0; + + (void) piix_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + /** * piix_config_drive_xfer_rate - set up an IDE device * @drive: IDE drive to configure @@ -315,7 +401,7 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -438,14 +524,26 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->ide_dma_clear_irq = &piix_dma_clear_irq; hwif->atapi_dma = 1; - - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; - if (hwif->ultra_mask & 0x78) { - if (!hwif->udma_four) - hwif->udma_four = piix_cable_detect(hwif); + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371SB_1: + hwif->ultra_mask = 0x80; + break; + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + hwif->ultra_mask = 0x07; + break; + default: + if (!hwif->udma_four) + hwif->udma_four = piix_cable_detect(hwif); + break; } if (no_piix_dma) @@ -459,7 +557,7 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->autodma; } -#define DECLARE_PIIX_DEV(name_str, udma) \ +#define DECLARE_PIIX_DEV(name_str) \ { \ .name = name_str, \ .init_chipset = init_chipset_piix, \ @@ -468,12 +566,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) .autodma = AUTODMA, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .bootable = ON_BOARD, \ - .udma_mask = udma, \ } static ide_pci_device_t piix_pci_info[] __devinitdata = { - /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */ - /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */ + /* 0 */ DECLARE_PIIX_DEV("PIIXa"), + /* 1 */ DECLARE_PIIX_DEV("PIIXb"), /* 2 */ { /* @@ -490,28 +587,28 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { .flags = IDEPCI_FLAG_ISA_PORTS }, - /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */ - /* 4 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 5 */ DECLARE_PIIX_DEV("ICH0", 0x07), /* udma0-2 */ - /* 6 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 7 */ DECLARE_PIIX_DEV("ICH", 0x1f), /* udma0-4 */ - /* 8 */ DECLARE_PIIX_DEV("PIIX4", 0x1f), /* udma0-4 */ - /* 9 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 10 */ DECLARE_PIIX_DEV("ICH2", 0x3f), /* udma0-5 */ - /* 11 */ DECLARE_PIIX_DEV("ICH2M", 0x3f), /* udma0-5 */ - /* 12 */ DECLARE_PIIX_DEV("ICH3M", 0x3f), /* udma0-5 */ - /* 13 */ DECLARE_PIIX_DEV("ICH3", 0x3f), /* udma0-5 */ - /* 14 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 15 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ - /* 16 */ DECLARE_PIIX_DEV("C-ICH", 0x3f), /* udma0-5 */ - /* 17 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA", 0x3f), /* udma0-5 */ - /* 19 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ - /* 20 */ DECLARE_PIIX_DEV("ICH6", 0x3f), /* udma0-5 */ - /* 21 */ DECLARE_PIIX_DEV("ICH7", 0x3f), /* udma0-5 */ - /* 22 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 23 */ DECLARE_PIIX_DEV("ESB2", 0x3f), /* udma0-5 */ - /* 24 */ DECLARE_PIIX_DEV("ICH8M", 0x3f), /* udma0-5 */ + /* 3 */ DECLARE_PIIX_DEV("PIIX3"), + /* 4 */ DECLARE_PIIX_DEV("PIIX4"), + /* 5 */ DECLARE_PIIX_DEV("ICH0"), + /* 6 */ DECLARE_PIIX_DEV("PIIX4"), + /* 7 */ DECLARE_PIIX_DEV("ICH"), + /* 8 */ DECLARE_PIIX_DEV("PIIX4"), + /* 9 */ DECLARE_PIIX_DEV("PIIX4"), + /* 10 */ DECLARE_PIIX_DEV("ICH2"), + /* 11 */ DECLARE_PIIX_DEV("ICH2M"), + /* 12 */ DECLARE_PIIX_DEV("ICH3M"), + /* 13 */ DECLARE_PIIX_DEV("ICH3"), + /* 14 */ DECLARE_PIIX_DEV("ICH4"), + /* 15 */ DECLARE_PIIX_DEV("ICH5"), + /* 16 */ DECLARE_PIIX_DEV("C-ICH"), + /* 17 */ DECLARE_PIIX_DEV("ICH4"), + /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA"), + /* 19 */ DECLARE_PIIX_DEV("ICH5"), + /* 20 */ DECLARE_PIIX_DEV("ICH6"), + /* 21 */ DECLARE_PIIX_DEV("ICH7"), + /* 22 */ DECLARE_PIIX_DEV("ICH4"), + /* 23 */ DECLARE_PIIX_DEV("ESB2"), + /* 24 */ DECLARE_PIIX_DEV("ICH8M"), }; /** diff --git a/trunk/drivers/ide/pci/scc_pata.c b/trunk/drivers/ide/pci/scc_pata.c index cbf936325355..f84bf791f72e 100644 --- a/trunk/drivers/ide/pci/scc_pata.c +++ b/trunk/drivers/ide/pci/scc_pata.c @@ -189,6 +189,23 @@ scc_ide_outsl(unsigned long port, void *addr, u32 count) } } +/** + * scc_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. + * Enforce UDMA33 as a limit if there is no 80pin cable present. + */ + +static u8 scc_ratemask(ide_drive_t *drive) +{ + u8 mode = 4; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * scc_tuneproc - tune a drive PIO mode * @drive: drive to tune @@ -256,7 +273,7 @@ static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted) static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed); struct scc_ports *ports = ide_get_hwifdata(hwif); unsigned long ctl_base = ports->ctl; unsigned long cckctrl_port = ctl_base + 0xff0; @@ -330,7 +347,7 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) static int scc_config_chipset_for_dma(ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, scc_ratemask(drive)); if (!speed) return 0; diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index 2fa6d92d16cc..dbcd37a0c652 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -65,16 +65,16 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static u8 svwks_udma_filter(ide_drive_t *drive) +static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mask = 0; + u8 mode = 0; if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) - return 0x1f; + return 2; if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -86,31 +86,25 @@ static u8 svwks_udma_filter(ide_drive_t *drive) if(drive->media == ide_disk) return 0; /* Check the OSB4 DMA33 enable bit */ - return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0; + return ((reg & 0x00004000) == 0x00004000) ? 1 : 0; } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { - return 0x07; + return 1; } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { - u8 btr = 0, mode; + u8 btr = 0; pci_read_config_byte(dev, 0x5A, &btr); mode = btr & 0x3; - + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); /* If someone decides to do UDMA133 on CSB5 the same issue will bite so be inclusive */ if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) mode = 2; - - switch(mode) { - case 2: mask = 0x1f; break; - case 1: mask = 0x07; break; - default: mask = 0x00; break; - } } if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && (!(PCI_FUNC(dev->devfn) & 1))) - mask = 0x1f; - - return mask; + mode = 2; + return mode; } static u8 svwks_csb_check (struct pci_dev *dev) @@ -147,7 +141,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) if (xferspeed == 255) /* PIO auto-tuning */ speed = XFER_PIO_0 + pio; else - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); /* If we are about to put a disk into UDMA mode we screwed up. Our code assumes we never _ever_ do this on an OSB4 */ @@ -310,7 +304,7 @@ static void svwks_tune_drive (ide_drive_t *drive, u8 pio) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); if (!(speed)) speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); @@ -506,7 +500,6 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) hwif->tuneproc = &svwks_tune_drive; hwif->speedproc = &svwks_tune_chipset; - hwif->udma_filter = &svwks_udma_filter; hwif->atapi_dma = 1; diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c index d3185e29a38e..fd09b295a69d 100644 --- a/trunk/drivers/ide/pci/sgiioc4.c +++ b/trunk/drivers/ide/pci/sgiioc4.c @@ -692,7 +692,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) return -EIO; /* Create /proc/ide entries */ - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c index d09e74c2996e..c0188de3cc66 100644 --- a/trunk/drivers/ide/pci/siimage.c +++ b/trunk/drivers/ide/pci/siimage.c @@ -122,41 +122,45 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) } /** - * sil_udma_filter - compute UDMA mask - * @drive: IDE device - * - * Compute the available UDMA speeds for the device on the interface. + * siimage_ratemask - Compute available modes + * @drive: IDE drive * + * Compute the available speeds for the devices on the interface. * For the CMD680 this depends on the clocking mode (scsc), for the - * SI3112 SATA controller life is a bit simpler. + * SI3312 SATA controller life is a bit simpler. Enforce UDMA33 + * as a limit if there is no 80pin cable present. */ - -static u8 sil_udma_filter(ide_drive_t *drive) + +static byte siimage_ratemask (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); + u8 mode = 0, scsc = 0; unsigned long base = (unsigned long) hwif->hwif_data; - u8 mask = 0, scsc = 0; if (hwif->mmio) scsc = hwif->INB(base + 0x4A); else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if (is_sata(hwif)) { - mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f; - goto out; + if(is_sata(hwif)) + { + if(strstr(drive->id->model, "Maxtor")) + return 3; + return 4; } - + if ((scsc & 0x30) == 0x10) /* 133 */ - mask = 0x7f; + mode = 4; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ - mask = 0x7f; + mode = 4; else if ((scsc & 0x30) == 0x00) /* 100 */ - mask = 0x3f; + mode = 3; else /* Disabled ? */ BUG(); -out: - return mask; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; } /** @@ -302,7 +306,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = HWIF(drive); u16 ultra = 0, multi = 0; u8 mode = 0, unit = drive->select.b.unit; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(siimage_ratemask(drive), xferspeed); unsigned long base = (unsigned long)hwif->hwif_data; u8 scsc = 0, addr_mask = ((hwif->channel) ? ((hwif->mmio) ? 0xF4 : 0x84) : @@ -385,7 +389,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); if (!speed) return 0; @@ -827,7 +831,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) /* * Now set up the hw. We have to do this ourselves as - * the MMIO layout isnt the same as the standard port + * the MMIO layout isnt the same as the the standard port * based I/O */ @@ -985,7 +989,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) hwif->tuneproc = &siimage_tuneproc; hwif->reset_poll = &siimage_reset_poll; hwif->pre_reset = &siimage_pre_reset; - hwif->udma_filter = &sil_udma_filter; if(is_sata(hwif)) { static int first = 1; diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index 2bde1b92784a..2ba0669f36a1 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -191,7 +191,7 @@ static char* chipset_capability[] = { "ATA 133 (1st gen)", "ATA 133 (2nd gen)" }; -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -426,7 +426,17 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) return len > count ? count : len; } -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static u8 sis5513_ratemask (ide_drive_t *drive) +{ + u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 }; + u8 mode = rates[chipset_family]; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} /* * Configuration functions @@ -553,7 +563,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) u8 drive_pci, reg, speed; u32 regdw; - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed); /* See config_art_rwp_pio for drive pci config registers */ drive_pci = 0x40; @@ -638,13 +648,32 @@ static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) (void) config_chipset_for_pio(drive, pio); } +/* + * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) + */ +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive)); + +#ifdef DEBUG + printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", + drive->dn, drive->id->dma_ultra); +#endif + + if (!(speed)) + return 0; + + sis5513_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int sis5513_config_xfer_rate(ide_drive_t *drive) { config_art_rwp_pio(drive, 5); drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -797,7 +826,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c break; } -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) if (!sis_proc) { sis_proc = 1; bmide_dev = dev; @@ -829,8 +858,6 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif) static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) { - u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; - hwif->autodma = 0; if (!hwif->irq) @@ -846,8 +873,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) } hwif->atapi_dma = 1; - - hwif->ultra_mask = udma_rates[chipset_family]; + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/trunk/drivers/ide/pci/slc90e66.c b/trunk/drivers/ide/pci/slc90e66.c index c40f291f91e0..852ccb36da1d 100644 --- a/trunk/drivers/ide/pci/slc90e66.c +++ b/trunk/drivers/ide/pci/slc90e66.c @@ -21,6 +21,15 @@ #include +static u8 slc90e66_ratemask (ide_drive_t *drive) +{ + u8 mode = 2; + + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + static u8 slc90e66_dma_2_pio (u8 xfer_rate) { switch(xfer_rate) { case XFER_UDMA_4: @@ -113,7 +122,7 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(slc90e66_ratemask(drive), xferspeed); int sitre = 0, a_speed = 7 << (drive->dn * 4); int u_speed = 0, u_flag = 1 << drive->dn; u16 reg4042, reg44, reg48, reg4a; @@ -160,11 +169,22 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +static int slc90e66_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive)); + + if (!speed) + return 0; + + (void) slc90e66_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/trunk/drivers/ide/pci/tc86c001.c b/trunk/drivers/ide/pci/tc86c001.c index cee619bb2eaf..0b6d81d6ce48 100644 --- a/trunk/drivers/ide/pci/tc86c001.c +++ b/trunk/drivers/ide/pci/tc86c001.c @@ -13,13 +13,18 @@ #include #include +static inline u8 tc86c001_ratemask(ide_drive_t *drive) +{ + return eighty_ninty_three(drive) ? 2 : 1; +} + static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); u16 mode, scr = hwif->INW(scr_port); - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(tc86c001_ratemask(drive), speed); switch (speed) { case XFER_UDMA_4: mode = 0x00c0; break; @@ -167,9 +172,20 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) return 0; } +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); + + if (!speed) + return 0; + + (void) tc86c001_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/trunk/drivers/ide/pci/triflex.c b/trunk/drivers/ide/pci/triflex.c index 35e8c612638f..5e06179c3469 100644 --- a/trunk/drivers/ide/pci/triflex.c +++ b/trunk/drivers/ide/pci/triflex.c @@ -48,7 +48,7 @@ static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) u16 timing = 0; u32 triflex_timings = 0; u8 unit = (drive->select.b.unit & 0x01); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(0, xferspeed); pci_read_config_dword(dev, channel_offset, &triflex_timings); @@ -100,9 +100,20 @@ static void triflex_tune_drive(ide_drive_t *drive, u8 pio) (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio)); } +static int triflex_config_drive_for_dma(ide_drive_t *drive) +{ + int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ + + if (!speed) + return 0; + + (void) triflex_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int triflex_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive)) return 0; triflex_tune_drive(drive, 255); diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c index 45fc36f0f219..a49ebe44babd 100644 --- a/trunk/drivers/ide/ppc/pmac.c +++ b/trunk/drivers/ide/ppc/pmac.c @@ -1276,8 +1276,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* We probe the hwif now */ probe_hwif_init(hwif); - ide_proc_register_port(hwif); - return 0; } diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index 67035ba4bf5e..118fb3205ca8 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -702,7 +702,6 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) { - ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index_list; int ret; @@ -711,19 +710,11 @@ int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) goto out; if ((index_list.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index_list.b.low]; + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup); if ((index_list.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index_list.b.high]; + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup); - if (hwif) - probe_hwif_init_with_fixup(hwif, d->fixup); - if (mate) - probe_hwif_init_with_fixup(mate, d->fixup); - - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); + create_proc_ide_interfaces(); out: return ret; } @@ -757,22 +748,13 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, } } - for (i = 0; i < 2; i++) { - u8 idx[2] = { index_list[i].b.low, index_list[i].b.high }; - int j; - - for (j = 0; j < 2; j++) { - if ((idx[j] & 0xf0) != 0xf0) - ide_proc_register_port(ide_hwifs + idx[j]); - } - } + create_proc_ide_interfaces(); out: return ret; } EXPORT_SYMBOL_GPL(ide_setup_pci_devices); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER /* * Module interfaces */ @@ -879,4 +861,3 @@ void __init ide_scan_pcibus (int scan_direction) __pci_register_driver(d, d->driver.owner, d->driver.mod_name); } } -#endif diff --git a/trunk/drivers/ieee1394/Kconfig b/trunk/drivers/ieee1394/Kconfig index 8012b3b0ce75..61d7809a5a26 100644 --- a/trunk/drivers/ieee1394/Kconfig +++ b/trunk/drivers/ieee1394/Kconfig @@ -1,7 +1,4 @@ menu "IEEE 1394 (FireWire) support" - depends on PCI || BROKEN - -source "drivers/firewire/Kconfig" config IEEE1394 tristate "IEEE 1394 (FireWire) support" diff --git a/trunk/drivers/ieee1394/nodemgr.c b/trunk/drivers/ieee1394/nodemgr.c index 835937e38529..6a1a0572275e 100644 --- a/trunk/drivers/ieee1394/nodemgr.c +++ b/trunk/drivers/ieee1394/nodemgr.c @@ -1702,7 +1702,7 @@ static int nodemgr_host_thread(void *__hi) generation = get_hpsb_generation(host); /* If we get a reset before we are done waiting, then - * start the waiting over again */ + * start the the waiting over again */ if (generation != g) g = generation, i = 0; } diff --git a/trunk/drivers/infiniband/Kconfig b/trunk/drivers/infiniband/Kconfig index 994decc7bcf2..66b36de9fa6f 100644 --- a/trunk/drivers/infiniband/Kconfig +++ b/trunk/drivers/infiniband/Kconfig @@ -1,5 +1,4 @@ menu "InfiniBand support" - depends on HAS_IOMEM config INFINIBAND depends on PCI || BROKEN @@ -30,11 +29,6 @@ config INFINIBAND_USER_ACCESS libibverbs, libibcm and a hardware driver library from . -config INFINIBAND_USER_MEM - bool - depends on INFINIBAND_USER_ACCESS != n - default y - config INFINIBAND_ADDR_TRANS bool depends on INFINIBAND && INET @@ -46,8 +40,6 @@ source "drivers/infiniband/hw/ehca/Kconfig" source "drivers/infiniband/hw/amso1100/Kconfig" source "drivers/infiniband/hw/cxgb3/Kconfig" -source "drivers/infiniband/hw/mlx4/Kconfig" - source "drivers/infiniband/ulp/ipoib/Kconfig" source "drivers/infiniband/ulp/srp/Kconfig" diff --git a/trunk/drivers/infiniband/Makefile b/trunk/drivers/infiniband/Makefile index 75f325e40b54..da2066c4f22c 100644 --- a/trunk/drivers/infiniband/Makefile +++ b/trunk/drivers/infiniband/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_INFINIBAND_IPATH) += hw/ipath/ obj-$(CONFIG_INFINIBAND_EHCA) += hw/ehca/ obj-$(CONFIG_INFINIBAND_AMSO1100) += hw/amso1100/ obj-$(CONFIG_INFINIBAND_CXGB3) += hw/cxgb3/ -obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/ 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 cb1ab3ea4998..189e5d4b9b17 100644 --- a/trunk/drivers/infiniband/core/Makefile +++ b/trunk/drivers/infiniband/core/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ device.o fmr_pool.o cache.o -ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o ib_mad-y := mad.o smi.o agent.o mad_rmpp.o @@ -29,4 +28,5 @@ ib_umad-y := user_mad.o ib_ucm-y := ucm.o -ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o +ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o \ + uverbs_marshall.o diff --git a/trunk/drivers/infiniband/core/device.c b/trunk/drivers/infiniband/core/device.c index 592c90aa3183..7fabb425b033 100644 --- a/trunk/drivers/infiniband/core/device.c +++ b/trunk/drivers/infiniband/core/device.c @@ -613,8 +613,6 @@ static void __exit ib_core_cleanup(void) { ib_cache_cleanup(); ib_sysfs_cleanup(); - /* Make sure that any pending umem accounting work is done. */ - flush_scheduled_work(); } module_init(ib_core_init); diff --git a/trunk/drivers/infiniband/core/uverbs.h b/trunk/drivers/infiniband/core/uverbs.h index c33546f9e961..102a59c033ff 100644 --- a/trunk/drivers/infiniband/core/uverbs.h +++ b/trunk/drivers/infiniband/core/uverbs.h @@ -45,7 +45,6 @@ #include #include -#include #include /* @@ -164,6 +163,11 @@ void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_event_handler(struct ib_event_handler *handler, struct ib_event *event); +int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, + void *addr, size_t size, int write); +void ib_umem_release(struct ib_device *dev, struct ib_umem *umem); +void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem); + #define IB_UVERBS_DECLARE_CMD(name) \ ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \ const char __user *buf, int in_len, \ diff --git a/trunk/drivers/infiniband/core/uverbs_cmd.c b/trunk/drivers/infiniband/core/uverbs_cmd.c index 01d70084aebe..bab66769be14 100644 --- a/trunk/drivers/infiniband/core/uverbs_cmd.c +++ b/trunk/drivers/infiniband/core/uverbs_cmd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * @@ -295,7 +295,6 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, INIT_LIST_HEAD(&ucontext->qp_list); INIT_LIST_HEAD(&ucontext->srq_list); INIT_LIST_HEAD(&ucontext->ah_list); - ucontext->closing = 0; resp.num_comp_vectors = file->device->num_comp_vectors; @@ -574,7 +573,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, struct ib_uverbs_reg_mr cmd; struct ib_uverbs_reg_mr_resp resp; struct ib_udata udata; - struct ib_uobject *uobj; + struct ib_umem_object *obj; struct ib_pd *pd; struct ib_mr *mr; int ret; @@ -600,21 +599,35 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE)) return -EINVAL; - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) + obj = kmalloc(sizeof *obj, GFP_KERNEL); + if (!obj) return -ENOMEM; - init_uobj(uobj, 0, file->ucontext, &mr_lock_key); - down_write(&uobj->mutex); + init_uobj(&obj->uobject, 0, file->ucontext, &mr_lock_key); + down_write(&obj->uobject.mutex); + + /* + * We ask for writable memory if any access flags other than + * "remote read" are set. "Local write" and "remote write" + * obviously require write access. "Remote atomic" can do + * things like fetch and add, which will modify memory, and + * "MW bind" can change permissions by binding a window. + */ + ret = ib_umem_get(file->device->ib_dev, &obj->umem, + (void *) (unsigned long) cmd.start, cmd.length, + !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ)); + if (ret) + goto err_free; + + obj->umem.virt_base = cmd.hca_va; pd = idr_read_pd(cmd.pd_handle, file->ucontext); if (!pd) { ret = -EINVAL; - goto err_free; + goto err_release; } - mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va, - cmd.access_flags, &udata); + mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); if (IS_ERR(mr)) { ret = PTR_ERR(mr); goto err_put; @@ -622,19 +635,19 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, mr->device = pd->device; mr->pd = pd; - mr->uobject = uobj; + mr->uobject = &obj->uobject; atomic_inc(&pd->usecnt); atomic_set(&mr->usecnt, 0); - uobj->object = mr; - ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj); + obj->uobject.object = mr; + ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject); if (ret) goto err_unreg; memset(&resp, 0, sizeof resp); resp.lkey = mr->lkey; resp.rkey = mr->rkey; - resp.mr_handle = uobj->id; + resp.mr_handle = obj->uobject.id; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -645,17 +658,17 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, put_pd_read(pd); mutex_lock(&file->mutex); - list_add_tail(&uobj->list, &file->ucontext->mr_list); + list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); mutex_unlock(&file->mutex); - uobj->live = 1; + obj->uobject.live = 1; - up_write(&uobj->mutex); + up_write(&obj->uobject.mutex); return in_len; err_copy: - idr_remove_uobj(&ib_uverbs_mr_idr, uobj); + idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject); err_unreg: ib_dereg_mr(mr); @@ -663,8 +676,11 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, err_put: put_pd_read(pd); +err_release: + ib_umem_release(file->device->ib_dev, &obj->umem); + err_free: - put_uobj_write(uobj); + put_uobj_write(&obj->uobject); return ret; } @@ -675,6 +691,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, struct ib_uverbs_dereg_mr cmd; struct ib_mr *mr; struct ib_uobject *uobj; + struct ib_umem_object *memobj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) @@ -684,7 +701,8 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, if (!uobj) return -EINVAL; - mr = uobj->object; + memobj = container_of(uobj, struct ib_umem_object, uobject); + mr = uobj->object; ret = ib_dereg_mr(mr); if (!ret) @@ -701,6 +719,8 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, list_del(&uobj->list); mutex_unlock(&file->mutex); + ib_umem_release(file->device->ib_dev, &memobj->umem); + put_uobj(uobj); return in_len; diff --git a/trunk/drivers/infiniband/core/uverbs_main.c b/trunk/drivers/infiniband/core/uverbs_main.c index 14d7ccd89195..d44e54799651 100644 --- a/trunk/drivers/infiniband/core/uverbs_main.c +++ b/trunk/drivers/infiniband/core/uverbs_main.c @@ -183,8 +183,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, if (!context) return 0; - context->closing = 1; - list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { struct ib_ah *ah = uobj->object; @@ -232,10 +230,16 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { struct ib_mr *mr = uobj->object; + struct ib_device *mrdev = mr->device; + struct ib_umem_object *memobj; idr_remove_uobj(&ib_uverbs_mr_idr, uobj); ib_dereg_mr(mr); - kfree(uobj); + + memobj = container_of(uobj, struct ib_umem_object, uobject); + ib_umem_release_on_close(mrdev, &memobj->umem); + + kfree(memobj); } list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { @@ -902,6 +906,7 @@ static void __exit ib_uverbs_cleanup(void) unregister_filesystem(&uverbs_event_fs); class_destroy(uverbs_class); unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); + flush_scheduled_work(); idr_destroy(&ib_uverbs_pd_idr); idr_destroy(&ib_uverbs_mr_idr); idr_destroy(&ib_uverbs_mw_idr); diff --git a/trunk/drivers/infiniband/core/umem.c b/trunk/drivers/infiniband/core/uverbs_mem.c similarity index 59% rename from trunk/drivers/infiniband/core/umem.c rename to trunk/drivers/infiniband/core/uverbs_mem.c index f32ca5fbb26b..c95fe952abd5 100644 --- a/trunk/drivers/infiniband/core/umem.c +++ b/trunk/drivers/infiniband/core/uverbs_mem.c @@ -39,6 +39,13 @@ #include "uverbs.h" +struct ib_umem_account_work { + struct work_struct work; + struct mm_struct *mm; + unsigned long diff; +}; + + static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty) { struct ib_umem_chunk *chunk, *tmp; @@ -57,56 +64,35 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d } } -/** - * ib_umem_get - Pin and DMA map userspace memory. - * @context: userspace context to pin memory for - * @addr: userspace virtual address to start at - * @size: length of region to pin - * @access: IB_ACCESS_xxx flags for memory being pinned - */ -struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, - size_t size, int access) +int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, + void *addr, size_t size, int write) { - struct ib_umem *umem; struct page **page_list; struct ib_umem_chunk *chunk; unsigned long locked; unsigned long lock_limit; unsigned long cur_base; unsigned long npages; - int ret; + int ret = 0; int off; int i; if (!can_do_mlock()) - return ERR_PTR(-EPERM); + return -EPERM; - umem = kmalloc(sizeof *umem, GFP_KERNEL); - if (!umem) - return ERR_PTR(-ENOMEM); - - umem->context = context; - umem->length = size; - umem->offset = addr & ~PAGE_MASK; - umem->page_size = PAGE_SIZE; - /* - * We ask for writable memory if any access flags other than - * "remote read" are set. "Local write" and "remote write" - * obviously require write access. "Remote atomic" can do - * things like fetch and add, which will modify memory, and - * "MW bind" can change permissions by binding a window. - */ - umem->writable = !!(access & ~IB_ACCESS_REMOTE_READ); + page_list = (struct page **) __get_free_page(GFP_KERNEL); + if (!page_list) + return -ENOMEM; - INIT_LIST_HEAD(&umem->chunk_list); + mem->user_base = (unsigned long) addr; + mem->length = size; + mem->offset = (unsigned long) addr & ~PAGE_MASK; + mem->page_size = PAGE_SIZE; + mem->writable = write; - page_list = (struct page **) __get_free_page(GFP_KERNEL); - if (!page_list) { - kfree(umem); - return ERR_PTR(-ENOMEM); - } + INIT_LIST_HEAD(&mem->chunk_list); - npages = PAGE_ALIGN(size + umem->offset) >> PAGE_SHIFT; + npages = PAGE_ALIGN(size + mem->offset) >> PAGE_SHIFT; down_write(¤t->mm->mmap_sem); @@ -118,13 +104,13 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, goto out; } - cur_base = addr & PAGE_MASK; + cur_base = (unsigned long) addr & PAGE_MASK; while (npages) { ret = get_user_pages(current, current->mm, cur_base, min_t(int, npages, PAGE_SIZE / sizeof (struct page *)), - 1, !umem->writable, page_list, NULL); + 1, !write, page_list, NULL); if (ret < 0) goto out; @@ -150,7 +136,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, chunk->page_list[i].length = PAGE_SIZE; } - chunk->nmap = ib_dma_map_sg(context->device, + chunk->nmap = ib_dma_map_sg(dev, &chunk->page_list[0], chunk->nents, DMA_BIDIRECTIONAL); @@ -165,94 +151,75 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ret -= chunk->nents; off += chunk->nents; - list_add_tail(&chunk->list, &umem->chunk_list); + list_add_tail(&chunk->list, &mem->chunk_list); } ret = 0; } out: - if (ret < 0) { - __ib_umem_release(context->device, umem, 0); - kfree(umem); - } else + if (ret < 0) + __ib_umem_release(dev, mem, 0); + else current->mm->locked_vm = locked; up_write(¤t->mm->mmap_sem); free_page((unsigned long) page_list); - return ret < 0 ? ERR_PTR(ret) : umem; + return ret; } -EXPORT_SYMBOL(ib_umem_get); -static void ib_umem_account(struct work_struct *work) +void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) { - struct ib_umem *umem = container_of(work, struct ib_umem, work); + __ib_umem_release(dev, umem, 1); - down_write(&umem->mm->mmap_sem); - umem->mm->locked_vm -= umem->diff; - up_write(&umem->mm->mmap_sem); - mmput(umem->mm); - kfree(umem); + down_write(¤t->mm->mmap_sem); + current->mm->locked_vm -= + PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; + up_write(¤t->mm->mmap_sem); } -/** - * ib_umem_release - release memory pinned with ib_umem_get - * @umem: umem struct to release - */ -void ib_umem_release(struct ib_umem *umem) +static void ib_umem_account(struct work_struct *_work) { - struct ib_ucontext *context = umem->context; + struct ib_umem_account_work *work = + container_of(_work, struct ib_umem_account_work, work); + + down_write(&work->mm->mmap_sem); + work->mm->locked_vm -= work->diff; + up_write(&work->mm->mmap_sem); + mmput(work->mm); + kfree(work); +} + +void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) +{ + struct ib_umem_account_work *work; struct mm_struct *mm; - unsigned long diff; - __ib_umem_release(umem->context->device, umem, 1); + __ib_umem_release(dev, umem, 1); mm = get_task_mm(current); if (!mm) return; - diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; - /* * We may be called with the mm's mmap_sem already held. This * can happen when a userspace munmap() is the call that drops * the last reference to our file and calls our release * method. If there are memory regions to destroy, we'll end - * up here and not be able to take the mmap_sem. In that case - * we defer the vm_locked accounting to the system workqueue. + * up here and not be able to take the mmap_sem. Therefore we + * defer the vm_locked accounting to the system workqueue. */ - if (context->closing && !down_write_trylock(&mm->mmap_sem)) { - INIT_WORK(&umem->work, ib_umem_account); - umem->mm = mm; - umem->diff = diff; - schedule_work(&umem->work); + work = kmalloc(sizeof *work, GFP_KERNEL); + if (!work) { + mmput(mm); return; - } else - down_write(&mm->mmap_sem); - - current->mm->locked_vm -= diff; - up_write(&mm->mmap_sem); - mmput(mm); - kfree(umem); -} -EXPORT_SYMBOL(ib_umem_release); - -int ib_umem_page_count(struct ib_umem *umem) -{ - struct ib_umem_chunk *chunk; - int shift; - int i; - int n; - - shift = ilog2(umem->page_size); + } - n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) - for (i = 0; i < chunk->nmap; ++i) - n += sg_dma_len(&chunk->page_list[i]) >> shift; + INIT_WORK(&work->work, ib_umem_account); + work->mm = mm; + work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; - return n; + schedule_work(&work->work); } -EXPORT_SYMBOL(ib_umem_page_count); diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c b/trunk/drivers/infiniband/hw/amso1100/c2_provider.c index 997cf1530762..109166223c09 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_provider.c @@ -56,7 +56,6 @@ #include #include -#include #include #include "c2.h" #include "c2_provider.h" @@ -397,7 +396,6 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd, } mr->pd = to_c2pd(ib_pd); - mr->umem = NULL; 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, @@ -430,8 +428,8 @@ static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc) return c2_reg_phys_mr(pd, &bl, 1, acc, &kva); } -static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +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; @@ -443,23 +441,15 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, 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; - c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(c2mr->umem)) { - err = PTR_ERR(c2mr->umem); - kfree(c2mr); - return ERR_PTR(err); - } - - shift = ffs(c2mr->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; pages = kmalloc(n * sizeof(u64), GFP_KERNEL); @@ -469,34 +459,35 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, } i = 0; - list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) { + 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]) + - (c2mr->umem->page_size * k); + (region->page_size * k); } } } - kva = virt; + kva = (u64)region->virt_base; err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), pages, - c2mr->umem->page_size, + region->page_size, i, - length, - c2mr->umem->offset, + region->length, + region->offset, &kva, c2_convert_access(acc), c2mr); kfree(pages); - if (err) - goto err; + if (err) { + kfree(c2mr); + return ERR_PTR(err); + } return &c2mr->ibmr; err: - ib_umem_release(c2mr->umem); kfree(c2mr); return ERR_PTR(err); } @@ -511,11 +502,8 @@ static int c2_dereg_mr(struct ib_mr *ib_mr) err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey); if (err) pr_debug("c2_stag_dealloc failed: %d\n", err); - else { - if (mr->umem) - ib_umem_release(mr->umem); + else kfree(mr); - } return err; } diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h b/trunk/drivers/infiniband/hw/amso1100/c2_provider.h index 1076df2ee96a..fc906223220f 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h +++ b/trunk/drivers/infiniband/hw/amso1100/c2_provider.h @@ -73,7 +73,6 @@ struct c2_pd { struct c2_mr { struct ib_mr ibmr; struct c2_pd *pd; - struct ib_umem *umem; }; struct c2_av; diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c index e7c2c3948037..a891493fd340 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include "cxio_hal.h" @@ -444,8 +443,6 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr) remove_handle(rhp, &rhp->mmidr, mmid); if (mhp->kva) kfree((void *) (unsigned long) mhp->kva); - if (mhp->umem) - ib_umem_release(mhp->umem); PDBG("%s mmid 0x%x ptr %p\n", __FUNCTION__, mmid, mhp); kfree(mhp); return 0; @@ -580,8 +577,8 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, } -static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int acc, struct ib_udata *udata) { __be64 *pages; int shift, n, len; @@ -594,6 +591,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct iwch_reg_user_mr_resp uresp; PDBG("%s ib_pd %p\n", __FUNCTION__, pd); + shift = ffs(region->page_size) - 1; php = to_iwch_pd(pd); rhp = php->rhp; @@ -601,17 +599,8 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, if (!mhp) return ERR_PTR(-ENOMEM); - mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(mhp->umem)) { - err = PTR_ERR(mhp->umem); - kfree(mhp); - return ERR_PTR(err); - } - - shift = ffs(mhp->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &mhp->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; pages = kmalloc(n * sizeof(u64), GFP_KERNEL); @@ -622,13 +611,13 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, i = n = 0; - list_for_each_entry(chunk, &mhp->umem->chunk_list, list) + 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++] = cpu_to_be64(sg_dma_address( &chunk->page_list[j]) + - mhp->umem->page_size * k); + region->page_size * k); } } @@ -636,9 +625,9 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; mhp->attr.perms = iwch_ib_to_tpt_access(acc); - mhp->attr.va_fbo = virt; + mhp->attr.va_fbo = region->virt_base; mhp->attr.page_size = shift - 12; - mhp->attr.len = (u32) length; + mhp->attr.len = (u32) region->length; mhp->attr.pbl_size = i; err = iwch_register_mem(rhp, php, mhp, shift, pages); kfree(pages); @@ -661,7 +650,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, return &mhp->ibmr; err: - ib_umem_release(mhp->umem); kfree(mhp); return ERR_PTR(err); } diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h index 48833f3f3bd0..93bcc56756bd 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -73,7 +73,6 @@ struct tpt_attributes { struct iwch_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct iwch_dev *rhp; u64 kva; struct tpt_attributes attr; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index f64d42b08674..10fb8fbafa0c 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -176,7 +176,6 @@ struct ehca_mr { 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; - struct ib_umem *umem; spinlock_t mrlock; enum ehca_mr_flag flags; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c index 82dda2faf4d0..f284be1c9166 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c @@ -745,7 +745,6 @@ static int comp_pool_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: 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); @@ -753,29 +752,24 @@ static int comp_pool_callback(struct notifier_block *nfb, } break; case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: 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: - case CPU_ONLINE_FROZEN: 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: - case CPU_DOWN_PREPARE_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu); break; case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu); destroy_comp_task(pool, cpu); take_over_work(pool, cpu); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h index 37e7fe0908cf..e14b029332c8 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -78,7 +78,8 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, int num_phys_buf, int mr_access_flags, u64 *iova_start); -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt, +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, diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c index 84c5bb498563..d22ab563633f 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -39,8 +39,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include "ehca_iverbs.h" @@ -240,8 +238,10 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, /*----------------------------------------------------------------------*/ -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt, - int mr_access_flags, struct ib_udata *udata) +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; @@ -257,7 +257,11 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt 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) && @@ -271,10 +275,17 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt 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 (length == 0 || virt + length < virt) { + if ((region->length == 0) || + ((region->virt_base + region->length) < region->virt_base)) { ehca_err(pd->device, "bad input values: length=%lx " - "virt_base=%lx", length, virt); + "virt_base=%lx", region->length, region->virt_base); ib_mr = ERR_PTR(-EINVAL); goto reg_user_mr_exit0; } @@ -286,55 +297,40 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt goto reg_user_mr_exit0; } - e_mr->umem = ib_umem_get(pd->uobject->context, start, length, - mr_access_flags); - if (IS_ERR(e_mr->umem)) { - ib_mr = (void *) e_mr->umem; - goto reg_user_mr_exit1; - } - - if (e_mr->umem->page_size != PAGE_SIZE) { - ehca_err(pd->device, "page size not supported, " - "e_mr->umem->page_size=%x", e_mr->umem->page_size); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit2; - } - /* determine number of MR pages */ - num_pages_mr = (((virt % PAGE_SIZE) + length + PAGE_SIZE - 1) / - PAGE_SIZE); - num_pages_4k = (((virt % EHCA_PAGESIZE) + length + EHCA_PAGESIZE - 1) / - EHCA_PAGESIZE); + 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 = e_mr->umem; - pginfo.next_4k = e_mr->umem->offset / EHCA_PAGESIZE; + pginfo.region = region; + pginfo.next_4k = region->offset / EHCA_PAGESIZE; pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk, - (&e_mr->umem->chunk_list), + (®ion->chunk_list), list); - ret = ehca_reg_mr(shca, e_mr, (u64*) virt, length, mr_access_flags, e_pd, - &pginfo, &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey); + 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_exit2; + goto reg_user_mr_exit1; } /* successful registration of all pages */ return &e_mr->ib.ib_mr; -reg_user_mr_exit2: - ib_umem_release(e_mr->umem); 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 mr_access_flags=%x" + ehca_err(pd->device, "rc=%lx pd=%p region=%p mr_access_flags=%x" " udata=%p", - PTR_ERR(ib_mr), pd, mr_access_flags, udata); + PTR_ERR(ib_mr), pd, region, mr_access_flags, udata); return ib_mr; } /* end ehca_reg_user_mr() */ @@ -600,9 +596,6 @@ int ehca_dereg_mr(struct ib_mr *mr) goto dereg_mr_exit0; } - if (e_mr->umem) - ib_umem_release(e_mr->umem); - /* successful deregistration */ ehca_mr_delete(e_mr); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c index bdeef8d4f279..31e70732e369 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include @@ -148,7 +147,6 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, mr->mr.offset = 0; mr->mr.access_flags = acc; mr->mr.max_segs = num_phys_buf; - mr->umem = NULL; m = 0; n = 0; @@ -172,56 +170,46 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, /** * ipath_reg_user_mr - register a userspace memory region * @pd: protection domain for this memory region - * @start: starting userspace address - * @length: length of region to register - * @virt_addr: virtual address to use (from HCA's point of view) + * @region: the user memory region * @mr_access_flags: access flags for this memory region * @udata: unused by the InfiniPath driver * * Returns the memory region on success, otherwise returns an errno. */ -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, - struct ib_udata *udata) +struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int mr_access_flags, struct ib_udata *udata) { struct ipath_mr *mr; - struct ib_umem *umem; struct ib_umem_chunk *chunk; int n, m, i; struct ib_mr *ret; - if (length == 0) { + if (region->length == 0) { ret = ERR_PTR(-EINVAL); goto bail; } - umem = ib_umem_get(pd->uobject->context, start, length, mr_access_flags); - if (IS_ERR(umem)) - return (void *) umem; - n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; mr = alloc_mr(n, &to_idev(pd->device)->lk_table); if (!mr) { ret = ERR_PTR(-ENOMEM); - ib_umem_release(umem); goto bail; } mr->mr.pd = pd; - mr->mr.user_base = start; - mr->mr.iova = virt_addr; - mr->mr.length = length; - mr->mr.offset = umem->offset; + mr->mr.user_base = region->user_base; + mr->mr.iova = region->virt_base; + mr->mr.length = region->length; + mr->mr.offset = region->offset; mr->mr.access_flags = mr_access_flags; mr->mr.max_segs = n; - mr->umem = umem; m = 0; n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) { + list_for_each_entry(chunk, ®ion->chunk_list, list) { for (i = 0; i < chunk->nents; i++) { void *vaddr; @@ -231,7 +219,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, goto bail; } mr->mr.map[m]->segs[n].vaddr = vaddr; - mr->mr.map[m]->segs[n].length = umem->page_size; + mr->mr.map[m]->segs[n].length = region->page_size; n++; if (n == IPATH_SEGSZ) { m++; @@ -265,10 +253,6 @@ int ipath_dereg_mr(struct ib_mr *ibmr) i--; kfree(mr->mr.map[i]); } - - if (mr->umem) - ib_umem_release(mr->umem); - kfree(mr); return 0; } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h index 088b837ebea8..7064fc222727 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -251,7 +251,6 @@ struct ipath_sge { /* Memory region */ struct ipath_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct ipath_mregion mr; /* must be last */ }; @@ -752,8 +751,8 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, struct ib_phys_buf *buffer_list, int num_phys_buf, int acc, u64 *iova_start); -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, +struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int mr_access_flags, struct ib_udata *udata); int ipath_dereg_mr(struct ib_mr *ibmr); diff --git a/trunk/drivers/infiniband/hw/mlx4/Kconfig b/trunk/drivers/infiniband/hw/mlx4/Kconfig deleted file mode 100644 index b8912cdb9663..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config MLX4_INFINIBAND - tristate "Mellanox ConnectX HCA support" - depends on INFINIBAND - select MLX4_CORE - ---help--- - This driver provides low-level InfiniBand support for - Mellanox ConnectX PCI Express host channel adapters (HCAs). - This is required to use InfiniBand protocols such as - IP-over-IB or SRP with these devices. diff --git a/trunk/drivers/infiniband/hw/mlx4/Makefile b/trunk/drivers/infiniband/hw/mlx4/Makefile deleted file mode 100644 index 70f09c7826da..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o - -mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o diff --git a/trunk/drivers/infiniband/hw/mlx4/ah.c b/trunk/drivers/infiniband/hw/mlx4/ah.c deleted file mode 100644 index c75ac9463e20..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/ah.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" - -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - struct mlx4_dev *dev = to_mdev(pd->device)->dev; - struct mlx4_ib_ah *ah; - - ah = kmalloc(sizeof *ah, GFP_ATOMIC); - if (!ah) - return ERR_PTR(-ENOMEM); - - memset(&ah->av, 0, sizeof ah->av); - - ah->av.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24)); - ah->av.g_slid = ah_attr->src_path_bits; - ah->av.dlid = cpu_to_be16(ah_attr->dlid); - if (ah_attr->static_rate) { - ah->av.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET; - while (ah->av.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && - !(1 << ah->av.stat_rate & dev->caps.stat_rate_support)) - --ah->av.stat_rate; - } - ah->av.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); - if (ah_attr->ah_flags & IB_AH_GRH) { - ah->av.g_slid |= 0x80; - ah->av.gid_index = ah_attr->grh.sgid_index; - ah->av.hop_limit = ah_attr->grh.hop_limit; - ah->av.sl_tclass_flowlabel |= - cpu_to_be32((ah_attr->grh.traffic_class << 20) | - ah_attr->grh.flow_label); - memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, 16); - } - - return &ah->ibah; -} - -int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) -{ - struct mlx4_ib_ah *ah = to_mah(ibah); - - memset(ah_attr, 0, sizeof *ah_attr); - ah_attr->dlid = be16_to_cpu(ah->av.dlid); - ah_attr->sl = be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28; - ah_attr->port_num = be32_to_cpu(ah->av.port_pd) >> 24; - if (ah->av.stat_rate) - ah_attr->static_rate = ah->av.stat_rate - MLX4_STAT_RATE_OFFSET; - ah_attr->src_path_bits = ah->av.g_slid & 0x7F; - - if (mlx4_ib_ah_grh_present(ah)) { - ah_attr->ah_flags = IB_AH_GRH; - - ah_attr->grh.traffic_class = - be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20; - ah_attr->grh.flow_label = - be32_to_cpu(ah->av.sl_tclass_flowlabel) & 0xfffff; - ah_attr->grh.hop_limit = ah->av.hop_limit; - ah_attr->grh.sgid_index = ah->av.gid_index; - memcpy(ah_attr->grh.dgid.raw, ah->av.dgid, 16); - } - - return 0; -} - -int mlx4_ib_destroy_ah(struct ib_ah *ah) -{ - kfree(to_mah(ah)); - return 0; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/cq.c b/trunk/drivers/infiniband/hw/mlx4/cq.c deleted file mode 100644 index b2a290c6703a..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/cq.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" -#include "user.h" - -static void mlx4_ib_cq_comp(struct mlx4_cq *cq) -{ - struct ib_cq *ibcq = &to_mibcq(cq)->ibcq; - ibcq->comp_handler(ibcq, ibcq->cq_context); -} - -static void mlx4_ib_cq_event(struct mlx4_cq *cq, enum mlx4_event type) -{ - struct ib_event event; - struct ib_cq *ibcq; - - if (type != MLX4_EVENT_TYPE_CQ_ERROR) { - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on CQ %06x\n", type, cq->cqn); - return; - } - - ibcq = &to_mibcq(cq)->ibcq; - if (ibcq->event_handler) { - event.device = ibcq->device; - event.event = IB_EVENT_CQ_ERR; - event.element.cq = ibcq; - ibcq->event_handler(&event, ibcq->cq_context); - } -} - -static void *get_cqe_from_buf(struct mlx4_ib_cq_buf *buf, int n) -{ - int offset = n * sizeof (struct mlx4_cqe); - - if (buf->buf.nbufs == 1) - return buf->buf.u.direct.buf + offset; - else - return buf->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void *get_cqe(struct mlx4_ib_cq *cq, int n) -{ - return get_cqe_from_buf(&cq->buf, n); -} - -static void *get_sw_cqe(struct mlx4_ib_cq *cq, int n) -{ - struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibcq.cqe); - - return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^ - !!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe; -} - -static struct mlx4_cqe *next_cqe_sw(struct mlx4_ib_cq *cq) -{ - return get_sw_cqe(cq, cq->mcq.cons_index); -} - -struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct mlx4_ib_cq *cq; - struct mlx4_uar *uar; - int buf_size; - int err; - - if (entries < 1 || entries > dev->dev->caps.max_cqes) - return ERR_PTR(-EINVAL); - - cq = kmalloc(sizeof *cq, GFP_KERNEL); - if (!cq) - return ERR_PTR(-ENOMEM); - - entries = roundup_pow_of_two(entries + 1); - cq->ibcq.cqe = entries - 1; - buf_size = entries * sizeof (struct mlx4_cqe); - spin_lock_init(&cq->lock); - - if (context) { - struct mlx4_ib_create_cq ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err_cq; - } - - cq->umem = ib_umem_get(context, ucmd.buf_addr, buf_size, - IB_ACCESS_LOCAL_WRITE); - if (IS_ERR(cq->umem)) { - err = PTR_ERR(cq->umem); - goto err_cq; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(cq->umem), - ilog2(cq->umem->page_size), &cq->buf.mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &cq->buf.mtt, cq->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(context), ucmd.db_addr, - &cq->db); - if (err) - goto err_mtt; - - uar = &to_mucontext(context)->uar; - } else { - err = mlx4_ib_db_alloc(dev, &cq->db, 1); - if (err) - goto err_cq; - - cq->mcq.set_ci_db = cq->db.db; - cq->mcq.arm_db = cq->db.db + 1; - *cq->mcq.set_ci_db = 0; - *cq->mcq.arm_db = 0; - - if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &cq->buf.buf)) { - err = -ENOMEM; - goto err_db; - } - - err = mlx4_mtt_init(dev->dev, cq->buf.buf.npages, cq->buf.buf.page_shift, - &cq->buf.mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &cq->buf.mtt, &cq->buf.buf); - if (err) - goto err_mtt; - - uar = &dev->priv_uar; - } - - err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, - cq->db.dma, &cq->mcq); - if (err) - goto err_dbmap; - - cq->mcq.comp = mlx4_ib_cq_comp; - cq->mcq.event = mlx4_ib_cq_event; - - if (context) - if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof (__u32))) { - err = -EFAULT; - goto err_dbmap; - } - - return &cq->ibcq; - -err_dbmap: - if (context) - mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db); - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt); - -err_buf: - if (context) - ib_umem_release(cq->umem); - else - mlx4_buf_free(dev->dev, entries * sizeof (struct mlx4_cqe), - &cq->buf.buf); - -err_db: - if (!context) - mlx4_ib_db_free(dev, &cq->db); - -err_cq: - kfree(cq); - - return ERR_PTR(err); -} - -int mlx4_ib_destroy_cq(struct ib_cq *cq) -{ - struct mlx4_ib_dev *dev = to_mdev(cq->device); - struct mlx4_ib_cq *mcq = to_mcq(cq); - - mlx4_cq_free(dev->dev, &mcq->mcq); - mlx4_mtt_cleanup(dev->dev, &mcq->buf.mtt); - - if (cq->uobject) { - mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db); - ib_umem_release(mcq->umem); - } else { - mlx4_buf_free(dev->dev, (cq->cqe + 1) * sizeof (struct mlx4_cqe), - &mcq->buf.buf); - mlx4_ib_db_free(dev, &mcq->db); - } - - kfree(mcq); - - return 0; -} - -static void dump_cqe(void *cqe) -{ - __be32 *buf = cqe; - - printk(KERN_DEBUG "CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n", - be32_to_cpu(buf[0]), be32_to_cpu(buf[1]), be32_to_cpu(buf[2]), - be32_to_cpu(buf[3]), be32_to_cpu(buf[4]), be32_to_cpu(buf[5]), - be32_to_cpu(buf[6]), be32_to_cpu(buf[7])); -} - -static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe, - struct ib_wc *wc) -{ - if (cqe->syndrome == MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR) { - printk(KERN_DEBUG "local QP operation err " - "(QPN %06x, WQE index %x, vendor syndrome %02x, " - "opcode = %02x)\n", - be32_to_cpu(cqe->my_qpn), be16_to_cpu(cqe->wqe_index), - cqe->vendor_err_syndrome, - cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK); - dump_cqe(cqe); - } - - switch (cqe->syndrome) { - case MLX4_CQE_SYNDROME_LOCAL_LENGTH_ERR: - wc->status = IB_WC_LOC_LEN_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR: - wc->status = IB_WC_LOC_QP_OP_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_PROT_ERR: - wc->status = IB_WC_LOC_PROT_ERR; - break; - case MLX4_CQE_SYNDROME_WR_FLUSH_ERR: - wc->status = IB_WC_WR_FLUSH_ERR; - break; - case MLX4_CQE_SYNDROME_MW_BIND_ERR: - wc->status = IB_WC_MW_BIND_ERR; - break; - case MLX4_CQE_SYNDROME_BAD_RESP_ERR: - wc->status = IB_WC_BAD_RESP_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_ACCESS_ERR: - wc->status = IB_WC_LOC_ACCESS_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR: - wc->status = IB_WC_REM_INV_REQ_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_ACCESS_ERR: - wc->status = IB_WC_REM_ACCESS_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_OP_ERR: - wc->status = IB_WC_REM_OP_ERR; - break; - case MLX4_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR: - wc->status = IB_WC_RETRY_EXC_ERR; - break; - case MLX4_CQE_SYNDROME_RNR_RETRY_EXC_ERR: - wc->status = IB_WC_RNR_RETRY_EXC_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR: - wc->status = IB_WC_REM_ABORT_ERR; - break; - default: - wc->status = IB_WC_GENERAL_ERR; - break; - } - - wc->vendor_err = cqe->vendor_err_syndrome; -} - -static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, - struct mlx4_ib_qp **cur_qp, - struct ib_wc *wc) -{ - struct mlx4_cqe *cqe; - struct mlx4_qp *mqp; - struct mlx4_ib_wq *wq; - struct mlx4_ib_srq *srq; - int is_send; - int is_error; - u16 wqe_ctr; - - cqe = next_cqe_sw(cq); - if (!cqe) - return -EAGAIN; - - ++cq->mcq.cons_index; - - /* - * Make sure we read CQ entry contents after we've checked the - * ownership bit. - */ - rmb(); - - is_send = cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK; - is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == - MLX4_CQE_OPCODE_ERROR; - - if (!*cur_qp || - (be32_to_cpu(cqe->my_qpn) & 0xffffff) != (*cur_qp)->mqp.qpn) { - /* - * We do not have to take the QP table lock here, - * because CQs will be locked while QPs are removed - * from the table. - */ - mqp = __mlx4_qp_lookup(to_mdev(cq->ibcq.device)->dev, - be32_to_cpu(cqe->my_qpn)); - if (unlikely(!mqp)) { - printk(KERN_WARNING "CQ %06x with entry for unknown QPN %06x\n", - cq->mcq.cqn, be32_to_cpu(cqe->my_qpn) & 0xffffff); - return -EINVAL; - } - - *cur_qp = to_mibqp(mqp); - } - - wc->qp = &(*cur_qp)->ibqp; - - if (is_send) { - wq = &(*cur_qp)->sq; - wqe_ctr = be16_to_cpu(cqe->wqe_index); - wq->tail += wqe_ctr - (u16) wq->tail; - wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)]; - ++wq->tail; - } else if ((*cur_qp)->ibqp.srq) { - srq = to_msrq((*cur_qp)->ibqp.srq); - wqe_ctr = be16_to_cpu(cqe->wqe_index); - wc->wr_id = srq->wrid[wqe_ctr]; - mlx4_ib_free_srq_wqe(srq, wqe_ctr); - } else { - wq = &(*cur_qp)->rq; - wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)]; - ++wq->tail; - } - - if (unlikely(is_error)) { - mlx4_ib_handle_error_cqe((struct mlx4_err_cqe *) cqe, wc); - return 0; - } - - wc->status = IB_WC_SUCCESS; - - if (is_send) { - wc->wc_flags = 0; - switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) { - case MLX4_OPCODE_RDMA_WRITE_IMM: - wc->wc_flags |= IB_WC_WITH_IMM; - case MLX4_OPCODE_RDMA_WRITE: - wc->opcode = IB_WC_RDMA_WRITE; - break; - case MLX4_OPCODE_SEND_IMM: - wc->wc_flags |= IB_WC_WITH_IMM; - case MLX4_OPCODE_SEND: - wc->opcode = IB_WC_SEND; - break; - case MLX4_OPCODE_RDMA_READ: - wc->opcode = IB_WC_SEND; - wc->byte_len = be32_to_cpu(cqe->byte_cnt); - break; - case MLX4_OPCODE_ATOMIC_CS: - wc->opcode = IB_WC_COMP_SWAP; - wc->byte_len = 8; - break; - case MLX4_OPCODE_ATOMIC_FA: - wc->opcode = IB_WC_FETCH_ADD; - wc->byte_len = 8; - break; - case MLX4_OPCODE_BIND_MW: - wc->opcode = IB_WC_BIND_MW; - break; - } - } else { - wc->byte_len = be32_to_cpu(cqe->byte_cnt); - - switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) { - case MLX4_RECV_OPCODE_RDMA_WRITE_IMM: - wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; - wc->wc_flags = IB_WC_WITH_IMM; - wc->imm_data = cqe->immed_rss_invalid; - break; - case MLX4_RECV_OPCODE_SEND: - wc->opcode = IB_WC_RECV; - wc->wc_flags = 0; - break; - case MLX4_RECV_OPCODE_SEND_IMM: - wc->opcode = IB_WC_RECV; - wc->wc_flags = IB_WC_WITH_IMM; - wc->imm_data = cqe->immed_rss_invalid; - break; - } - - wc->slid = be16_to_cpu(cqe->rlid); - wc->sl = cqe->sl >> 4; - wc->src_qp = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff; - wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f; - wc->wc_flags |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ? - IB_WC_GRH : 0; - wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) >> 16; - } - - return 0; -} - -int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) -{ - struct mlx4_ib_cq *cq = to_mcq(ibcq); - struct mlx4_ib_qp *cur_qp = NULL; - unsigned long flags; - int npolled; - int err = 0; - - spin_lock_irqsave(&cq->lock, flags); - - for (npolled = 0; npolled < num_entries; ++npolled) { - err = mlx4_ib_poll_one(cq, &cur_qp, wc + npolled); - if (err) - break; - } - - if (npolled) - mlx4_cq_set_ci(&cq->mcq); - - spin_unlock_irqrestore(&cq->lock, flags); - - if (err == 0 || err == -EAGAIN) - return npolled; - else - return err; -} - -int mlx4_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) -{ - mlx4_cq_arm(&to_mcq(ibcq)->mcq, - (flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ? - MLX4_CQ_DB_REQ_NOT_SOL : MLX4_CQ_DB_REQ_NOT, - to_mdev(ibcq->device)->uar_map, - MLX4_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->uar_lock)); - - return 0; -} - -void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq) -{ - u32 prod_index; - int nfreed = 0; - struct mlx4_cqe *cqe; - - /* - * First we need to find the current producer index, so we - * know where to start cleaning from. It doesn't matter if HW - * adds new entries after this loop -- the QP we're worried - * about is already in RESET, so the new entries won't come - * from our QP and therefore don't need to be checked. - */ - for (prod_index = cq->mcq.cons_index; get_sw_cqe(cq, prod_index); ++prod_index) - if (prod_index == cq->mcq.cons_index + cq->ibcq.cqe) - break; - - /* - * Now sweep backwards through the CQ, removing CQ entries - * that match our QP by copying older entries on top of them. - */ - while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) { - cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); - if ((be32_to_cpu(cqe->my_qpn) & 0xffffff) == qpn) { - if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK)) - mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index)); - ++nfreed; - } else if (nfreed) - memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe), - cqe, sizeof *cqe); - } - - if (nfreed) { - cq->mcq.cons_index += nfreed; - /* - * Make sure update of buffer contents is done before - * updating consumer index. - */ - wmb(); - mlx4_cq_set_ci(&cq->mcq); - } -} - -void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq) -{ - spin_lock_irq(&cq->lock); - __mlx4_ib_cq_clean(cq, qpn, srq); - spin_unlock_irq(&cq->lock); -} diff --git a/trunk/drivers/infiniband/hw/mlx4/doorbell.c b/trunk/drivers/infiniband/hw/mlx4/doorbell.c deleted file mode 100644 index 1c36087aef14..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/doorbell.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" - -struct mlx4_ib_db_pgdir { - struct list_head list; - DECLARE_BITMAP(order0, MLX4_IB_DB_PER_PAGE); - DECLARE_BITMAP(order1, MLX4_IB_DB_PER_PAGE / 2); - unsigned long *bits[2]; - __be32 *db_page; - dma_addr_t db_dma; -}; - -static struct mlx4_ib_db_pgdir *mlx4_ib_alloc_db_pgdir(struct mlx4_ib_dev *dev) -{ - struct mlx4_ib_db_pgdir *pgdir; - - pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL); - if (!pgdir) - return NULL; - - bitmap_fill(pgdir->order1, MLX4_IB_DB_PER_PAGE / 2); - pgdir->bits[0] = pgdir->order0; - pgdir->bits[1] = pgdir->order1; - pgdir->db_page = dma_alloc_coherent(dev->ib_dev.dma_device, - PAGE_SIZE, &pgdir->db_dma, - GFP_KERNEL); - if (!pgdir->db_page) { - kfree(pgdir); - return NULL; - } - - return pgdir; -} - -static int mlx4_ib_alloc_db_from_pgdir(struct mlx4_ib_db_pgdir *pgdir, - struct mlx4_ib_db *db, int order) -{ - int o; - int i; - - for (o = order; o <= 1; ++o) { - i = find_first_bit(pgdir->bits[o], MLX4_IB_DB_PER_PAGE >> o); - if (i < MLX4_IB_DB_PER_PAGE >> o) - goto found; - } - - return -ENOMEM; - -found: - clear_bit(i, pgdir->bits[o]); - - i <<= o; - - if (o > order) - set_bit(i ^ 1, pgdir->bits[order]); - - db->u.pgdir = pgdir; - db->index = i; - db->db = pgdir->db_page + db->index; - db->dma = pgdir->db_dma + db->index * 4; - db->order = order; - - return 0; -} - -int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order) -{ - struct mlx4_ib_db_pgdir *pgdir; - int ret = 0; - - mutex_lock(&dev->pgdir_mutex); - - list_for_each_entry(pgdir, &dev->pgdir_list, list) - if (!mlx4_ib_alloc_db_from_pgdir(pgdir, db, order)) - goto out; - - pgdir = mlx4_ib_alloc_db_pgdir(dev); - if (!pgdir) { - ret = -ENOMEM; - goto out; - } - - list_add(&pgdir->list, &dev->pgdir_list); - - /* This should never fail -- we just allocated an empty page: */ - WARN_ON(mlx4_ib_alloc_db_from_pgdir(pgdir, db, order)); - -out: - mutex_unlock(&dev->pgdir_mutex); - - return ret; -} - -void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db) -{ - int o; - int i; - - mutex_lock(&dev->pgdir_mutex); - - o = db->order; - i = db->index; - - if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) { - clear_bit(i ^ 1, db->u.pgdir->order0); - ++o; - } - - i >>= o; - set_bit(i, db->u.pgdir->bits[o]); - - if (bitmap_full(db->u.pgdir->order1, MLX4_IB_DB_PER_PAGE / 2)) { - dma_free_coherent(dev->ib_dev.dma_device, PAGE_SIZE, - db->u.pgdir->db_page, db->u.pgdir->db_dma); - list_del(&db->u.pgdir->list); - kfree(db->u.pgdir); - } - - mutex_unlock(&dev->pgdir_mutex); -} - -struct mlx4_ib_user_db_page { - struct list_head list; - struct ib_umem *umem; - unsigned long user_virt; - int refcnt; -}; - -int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, - struct mlx4_ib_db *db) -{ - struct mlx4_ib_user_db_page *page; - struct ib_umem_chunk *chunk; - int err = 0; - - mutex_lock(&context->db_page_mutex); - - list_for_each_entry(page, &context->db_page_list, list) - if (page->user_virt == (virt & PAGE_MASK)) - goto found; - - page = kmalloc(sizeof *page, GFP_KERNEL); - if (!page) { - err = -ENOMEM; - goto out; - } - - page->user_virt = (virt & PAGE_MASK); - page->refcnt = 0; - page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK, - PAGE_SIZE, 0); - if (IS_ERR(page->umem)) { - err = PTR_ERR(page->umem); - kfree(page); - goto out; - } - - list_add(&page->list, &context->db_page_list); - -found: - chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); - db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK); - db->u.user_page = page; - ++page->refcnt; - -out: - mutex_unlock(&context->db_page_mutex); - - return err; -} - -void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db) -{ - mutex_lock(&context->db_page_mutex); - - if (!--db->u.user_page->refcnt) { - list_del(&db->u.user_page->list); - ib_umem_release(db->u.user_page->umem); - kfree(db->u.user_page); - } - - mutex_unlock(&context->db_page_mutex); -} diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c deleted file mode 100644 index 333091787c5f..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" - -enum { - MLX4_IB_VENDOR_CLASS1 = 0x9, - MLX4_IB_VENDOR_CLASS2 = 0xa -}; - -int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, - int port, struct ib_wc *in_wc, struct ib_grh *in_grh, - void *in_mad, void *response_mad) -{ - struct mlx4_cmd_mailbox *inmailbox, *outmailbox; - void *inbox; - int err; - u32 in_modifier = port; - u8 op_modifier = 0; - - inmailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(inmailbox)) - return PTR_ERR(inmailbox); - inbox = inmailbox->buf; - - outmailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(outmailbox)) { - mlx4_free_cmd_mailbox(dev->dev, inmailbox); - return PTR_ERR(outmailbox); - } - - memcpy(inbox, in_mad, 256); - - /* - * Key check traps can't be generated unless we have in_wc to - * tell us where to send the trap. - */ - if (ignore_mkey || !in_wc) - op_modifier |= 0x1; - if (ignore_bkey || !in_wc) - op_modifier |= 0x2; - - if (in_wc) { - struct { - __be32 my_qpn; - u32 reserved1; - __be32 rqpn; - u8 sl; - u8 g_path; - u16 reserved2[2]; - __be16 pkey; - u32 reserved3[11]; - u8 grh[40]; - } *ext_info; - - memset(inbox + 256, 0, 256); - ext_info = inbox + 256; - - ext_info->my_qpn = cpu_to_be32(in_wc->qp->qp_num); - ext_info->rqpn = cpu_to_be32(in_wc->src_qp); - ext_info->sl = in_wc->sl << 4; - ext_info->g_path = in_wc->dlid_path_bits | - (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); - ext_info->pkey = cpu_to_be16(in_wc->pkey_index); - - if (in_grh) - memcpy(ext_info->grh, in_grh, 40); - - op_modifier |= 0x4; - - in_modifier |= in_wc->slid << 16; - } - - err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, - in_modifier, op_modifier, - MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); - - if (!err); - memcpy(response_mad, outmailbox->buf, 256); - - mlx4_free_cmd_mailbox(dev->dev, inmailbox); - mlx4_free_cmd_mailbox(dev->dev, outmailbox); - - return err; -} - -static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) -{ - struct ib_ah *new_ah; - struct ib_ah_attr ah_attr; - - if (!dev->send_agent[port_num - 1][0]) - return; - - memset(&ah_attr, 0, sizeof ah_attr); - ah_attr.dlid = lid; - ah_attr.sl = sl; - ah_attr.port_num = port_num; - - new_ah = ib_create_ah(dev->send_agent[port_num - 1][0]->qp->pd, - &ah_attr); - if (IS_ERR(new_ah)) - return; - - spin_lock(&dev->sm_lock); - if (dev->sm_ah[port_num - 1]) - ib_destroy_ah(dev->sm_ah[port_num - 1]); - dev->sm_ah[port_num - 1] = new_ah; - spin_unlock(&dev->sm_lock); -} - -/* - * Snoop SM MADs for port info and P_Key table sets, so we can - * synthesize LID change and P_Key change events. - */ -static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) -{ - struct ib_event event; - - if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && - mad->mad_hdr.method == IB_MGMT_METHOD_SET) { - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { - struct ib_port_info *pinfo = - (struct ib_port_info *) ((struct ib_smp *) mad)->data; - - update_sm_ah(to_mdev(ibdev), port_num, - be16_to_cpu(pinfo->sm_lid), - pinfo->neighbormtu_mastersmsl & 0xf); - - event.device = ibdev; - event.element.port_num = port_num; - - if(pinfo->clientrereg_resv_subnetto & 0x80) - event.event = IB_EVENT_CLIENT_REREGISTER; - else - event.event = IB_EVENT_LID_CHANGE; - - ib_dispatch_event(&event); - } - - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { - event.device = ibdev; - event.event = IB_EVENT_PKEY_CHANGE; - event.element.port_num = port_num; - ib_dispatch_event(&event); - } - } -} - -static void node_desc_override(struct ib_device *dev, - struct ib_mad *mad) -{ - if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && - mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP && - mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { - spin_lock(&to_mdev(dev)->sm_lock); - memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); - spin_unlock(&to_mdev(dev)->sm_lock); - } -} - -static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *mad) -{ - int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; - struct ib_mad_send_buf *send_buf; - struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn]; - int ret; - - if (agent) { - send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, - IB_MGMT_MAD_DATA, GFP_ATOMIC); - /* - * We rely here on the fact that MLX QPs don't use the - * address handle after the send is posted (this is - * wrong following the IB spec strictly, but we know - * it's OK for our devices). - */ - spin_lock(&dev->sm_lock); - memcpy(send_buf->mad, mad, sizeof *mad); - if ((send_buf->ah = dev->sm_ah[port_num - 1])) - ret = ib_post_send_mad(send_buf, NULL); - else - ret = -EINVAL; - spin_unlock(&dev->sm_lock); - - if (ret) - ib_free_send_mad(send_buf); - } -} - -int mlx4_ib_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) -{ - u16 slid; - int err; - - slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); - - if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0) { - forward_trap(to_mdev(ibdev), port_num, in_mad); - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - } - - if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { - if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_SET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_TRAP_REPRESS) - return IB_MAD_RESULT_SUCCESS; - - /* - * Don't process SMInfo queries or vendor-specific - * MADs -- the SMA can't handle them. - */ - if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO || - ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) == - IB_SMP_ATTR_VENDOR_MASK)) - return IB_MAD_RESULT_SUCCESS; - } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || - in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 || - in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS2) { - if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_SET) - return IB_MAD_RESULT_SUCCESS; - } else - return IB_MAD_RESULT_SUCCESS; - - err = mlx4_MAD_IFC(to_mdev(ibdev), - mad_flags & IB_MAD_IGNORE_MKEY, - mad_flags & IB_MAD_IGNORE_BKEY, - port_num, in_wc, in_grh, in_mad, out_mad); - if (err) - return IB_MAD_RESULT_FAILURE; - - if (!out_mad->mad_hdr.status) { - smp_snoop(ibdev, port_num, in_mad); - node_desc_override(ibdev, out_mad); - } - - /* set return bit in status of directed route responses */ - if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) - out_mad->mad_hdr.status |= cpu_to_be16(1 << 15); - - if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) - /* no response for trap repress */ - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; -} - -static void send_handler(struct ib_mad_agent *agent, - struct ib_mad_send_wc *mad_send_wc) -{ - ib_free_send_mad(mad_send_wc->send_buf); -} - -int mlx4_ib_mad_init(struct mlx4_ib_dev *dev) -{ - struct ib_mad_agent *agent; - int p, q; - int ret; - - for (p = 0; p < dev->dev->caps.num_ports; ++p) - for (q = 0; q <= 1; ++q) { - agent = ib_register_mad_agent(&dev->ib_dev, p + 1, - q ? IB_QPT_GSI : IB_QPT_SMI, - NULL, 0, send_handler, - NULL, NULL); - if (IS_ERR(agent)) { - ret = PTR_ERR(agent); - goto err; - } - dev->send_agent[p][q] = agent; - } - - return 0; - -err: - for (p = 0; p < dev->dev->caps.num_ports; ++p) - for (q = 0; q <= 1; ++q) - if (dev->send_agent[p][q]) - ib_unregister_mad_agent(dev->send_agent[p][q]); - - return ret; -} - -void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev) -{ - struct ib_mad_agent *agent; - int p, q; - - for (p = 0; p < dev->dev->caps.num_ports; ++p) { - for (q = 0; q <= 1; ++q) { - agent = dev->send_agent[p][q]; - dev->send_agent[p][q] = NULL; - ib_unregister_mad_agent(agent); - } - - if (dev->sm_ah[p]) - ib_destroy_ah(dev->sm_ah[p]); - } -} diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c deleted file mode 100644 index 688ecb4c39f3..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4_ib.h" -#include "user.h" - -#define DRV_NAME "mlx4_ib" -#define DRV_VERSION "0.01" -#define DRV_RELDATE "May 1, 2006" - -MODULE_AUTHOR("Roland Dreier"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -static const char mlx4_ib_version[] __devinitdata = - DRV_NAME ": Mellanox ConnectX InfiniBand driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; - -static void init_query_mad(struct ib_smp *mad) -{ - mad->base_version = 1; - mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - mad->class_version = 1; - mad->method = IB_MGMT_METHOD_GET; -} - -static int mlx4_ib_query_device(struct ib_device *ibdev, - struct ib_device_attr *props) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memset(props, 0, sizeof *props); - - props->fw_ver = dev->dev->caps.fw_ver; - props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | - IB_DEVICE_PORT_ACTIVE_EVENT | - IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_RC_RNR_NAK_GEN; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR) - props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR) - props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM) - props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT) - props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; - - props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & - 0xffffff; - props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); - props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); - memcpy(&props->sys_image_guid, out_mad->data + 4, 8); - - props->max_mr_size = ~0ull; - props->page_size_cap = dev->dev->caps.page_size_cap; - props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; - props->max_qp_wr = dev->dev->caps.max_wqes; - props->max_sge = min(dev->dev->caps.max_sq_sg, - dev->dev->caps.max_rq_sg); - props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; - props->max_cqe = dev->dev->caps.max_cqes; - props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; - props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; - props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; - props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; - props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; - props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; - props->max_srq_wr = dev->dev->caps.max_srq_wqes; - props->max_srq_sge = dev->dev->caps.max_srq_sge; - props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay; - props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ? - IB_ATOMIC_HCA : IB_ATOMIC_NONE; - props->max_pkeys = dev->dev->caps.pkey_table_len; - props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms; - props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm; - props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * - props->max_mcast_grp; - props->max_map_per_fmr = (1 << (32 - ilog2(dev->dev->caps.num_mpts))) - 1; - -out: - kfree(in_mad); - kfree(out_mad); - - return err; -} - -static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, - struct ib_port_attr *props) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - memset(props, 0, sizeof *props); - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16)); - props->lmc = out_mad->data[34] & 0x7; - props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18)); - props->sm_sl = out_mad->data[36] & 0xf; - props->state = out_mad->data[32] & 0xf; - props->phys_state = out_mad->data[33] >> 4; - props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20)); - props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len; - props->max_msg_sz = 0x80000000; - props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len; - props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); - props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48)); - props->active_width = out_mad->data[31] & 0xf; - props->active_speed = out_mad->data[35] >> 4; - props->max_mtu = out_mad->data[41] & 0xf; - props->active_mtu = out_mad->data[36] >> 4; - props->subnet_timeout = out_mad->data[51] & 0x1f; - props->max_vl_num = out_mad->data[37] >> 4; - props->init_type_reply = out_mad->data[41] >> 4; - -out: - kfree(in_mad); - kfree(out_mad); - - return err; -} - -static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, - union ib_gid *gid) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(gid->raw, out_mad->data + 8, 8); - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; - in_mad->attr_mod = cpu_to_be32(index / 8); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, - u16 *pkey) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; - in_mad->attr_mod = cpu_to_be32(index / 32); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, - struct ib_device_modify *props) -{ - if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) - return -EOPNOTSUPP; - - if (mask & IB_DEVICE_MODIFY_NODE_DESC) { - spin_lock(&to_mdev(ibdev)->sm_lock); - memcpy(ibdev->node_desc, props->node_desc, 64); - spin_unlock(&to_mdev(ibdev)->sm_lock); - } - - return 0; -} - -static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols, - u32 cap_mask) -{ - struct mlx4_cmd_mailbox *mailbox; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memset(mailbox->buf, 0, 256); - *(u8 *) mailbox->buf = !!reset_qkey_viols << 6; - ((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask); - - err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev->dev, mailbox); - return err; -} - -static int mlx4_ib_modify_port(struct ib_device *ibdev, u8 port, int mask, - struct ib_port_modify *props) -{ - struct ib_port_attr attr; - u32 cap_mask; - int err; - - mutex_lock(&to_mdev(ibdev)->cap_mask_mutex); - - err = mlx4_ib_query_port(ibdev, port, &attr); - if (err) - goto out; - - cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) & - ~props->clr_port_cap_mask; - - err = mlx4_SET_PORT(to_mdev(ibdev), port, - !!(mask & IB_PORT_RESET_QKEY_CNTR), - cap_mask); - -out: - mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex); - return err; -} - -static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct mlx4_ib_ucontext *context; - struct mlx4_ib_alloc_ucontext_resp resp; - int err; - - resp.qp_tab_size = dev->dev->caps.num_qps; - resp.bf_reg_size = dev->dev->caps.bf_reg_size; - resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page; - - context = kmalloc(sizeof *context, GFP_KERNEL); - if (!context) - return ERR_PTR(-ENOMEM); - - err = mlx4_uar_alloc(to_mdev(ibdev)->dev, &context->uar); - if (err) { - kfree(context); - return ERR_PTR(err); - } - - INIT_LIST_HEAD(&context->db_page_list); - mutex_init(&context->db_page_mutex); - - err = ib_copy_to_udata(udata, &resp, sizeof resp); - if (err) { - mlx4_uar_free(to_mdev(ibdev)->dev, &context->uar); - kfree(context); - return ERR_PTR(-EFAULT); - } - - return &context->ibucontext; -} - -static int mlx4_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) -{ - struct mlx4_ib_ucontext *context = to_mucontext(ibcontext); - - mlx4_uar_free(to_mdev(ibcontext->device)->dev, &context->uar); - kfree(context); - - return 0; -} - -static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - struct mlx4_ib_dev *dev = to_mdev(context->device); - - if (vma->vm_end - vma->vm_start != PAGE_SIZE) - return -EINVAL; - - if (vma->vm_pgoff == 0) { - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, - to_mucontext(context)->uar.pfn, - PAGE_SIZE, vma->vm_page_prot)) - return -EAGAIN; - } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) { - /* FIXME want pgprot_writecombine() for BlueFlame pages */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, - to_mucontext(context)->uar.pfn + - dev->dev->caps.num_uars, - PAGE_SIZE, vma->vm_page_prot)) - return -EAGAIN; - } else - return -EINVAL; - - return 0; -} - -static struct ib_pd *mlx4_ib_alloc_pd(struct ib_device *ibdev, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct mlx4_ib_pd *pd; - int err; - - pd = kmalloc(sizeof *pd, GFP_KERNEL); - if (!pd) - return ERR_PTR(-ENOMEM); - - err = mlx4_pd_alloc(to_mdev(ibdev)->dev, &pd->pdn); - if (err) { - kfree(pd); - return ERR_PTR(err); - } - - if (context) - if (ib_copy_to_udata(udata, &pd->pdn, sizeof (__u32))) { - mlx4_pd_free(to_mdev(ibdev)->dev, pd->pdn); - kfree(pd); - return ERR_PTR(-EFAULT); - } - - return &pd->ibpd; -} - -static int mlx4_ib_dealloc_pd(struct ib_pd *pd) -{ - mlx4_pd_free(to_mdev(pd->device)->dev, to_mpd(pd)->pdn); - kfree(pd); - - return 0; -} - -static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - return mlx4_multicast_attach(to_mdev(ibqp->device)->dev, - &to_mqp(ibqp)->mqp, gid->raw); -} - -static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - return mlx4_multicast_detach(to_mdev(ibqp->device)->dev, - &to_mqp(ibqp)->mqp, gid->raw); -} - -static int init_node_data(struct mlx4_ib_dev *dev) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; - - err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(dev->ib_dev.node_desc, out_mad->data, 64); - - in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; - - err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static void *mlx4_ib_add(struct mlx4_dev *dev) -{ - struct mlx4_ib_dev *ibdev; - - ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev); - if (!ibdev) { - dev_err(&dev->pdev->dev, "Device struct alloc failed\n"); - return NULL; - } - - if (mlx4_pd_alloc(dev, &ibdev->priv_pdn)) - goto err_dealloc; - - if (mlx4_uar_alloc(dev, &ibdev->priv_uar)) - goto err_pd; - - ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!ibdev->uar_map) - goto err_uar; - - INIT_LIST_HEAD(&ibdev->pgdir_list); - mutex_init(&ibdev->pgdir_mutex); - - ibdev->dev = dev; - - strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX); - ibdev->ib_dev.owner = THIS_MODULE; - ibdev->ib_dev.node_type = RDMA_NODE_IB_CA; - ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports; - ibdev->ib_dev.num_comp_vectors = 1; - ibdev->ib_dev.dma_device = &dev->pdev->dev; - - ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION; - ibdev->ib_dev.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_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_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | - (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); - - ibdev->ib_dev.query_device = mlx4_ib_query_device; - ibdev->ib_dev.query_port = mlx4_ib_query_port; - ibdev->ib_dev.query_gid = mlx4_ib_query_gid; - ibdev->ib_dev.query_pkey = mlx4_ib_query_pkey; - ibdev->ib_dev.modify_device = mlx4_ib_modify_device; - ibdev->ib_dev.modify_port = mlx4_ib_modify_port; - ibdev->ib_dev.alloc_ucontext = mlx4_ib_alloc_ucontext; - ibdev->ib_dev.dealloc_ucontext = mlx4_ib_dealloc_ucontext; - ibdev->ib_dev.mmap = mlx4_ib_mmap; - ibdev->ib_dev.alloc_pd = mlx4_ib_alloc_pd; - ibdev->ib_dev.dealloc_pd = mlx4_ib_dealloc_pd; - ibdev->ib_dev.create_ah = mlx4_ib_create_ah; - ibdev->ib_dev.query_ah = mlx4_ib_query_ah; - ibdev->ib_dev.destroy_ah = mlx4_ib_destroy_ah; - ibdev->ib_dev.create_srq = mlx4_ib_create_srq; - ibdev->ib_dev.modify_srq = mlx4_ib_modify_srq; - ibdev->ib_dev.destroy_srq = mlx4_ib_destroy_srq; - ibdev->ib_dev.post_srq_recv = mlx4_ib_post_srq_recv; - ibdev->ib_dev.create_qp = mlx4_ib_create_qp; - ibdev->ib_dev.modify_qp = mlx4_ib_modify_qp; - ibdev->ib_dev.destroy_qp = mlx4_ib_destroy_qp; - ibdev->ib_dev.post_send = mlx4_ib_post_send; - ibdev->ib_dev.post_recv = mlx4_ib_post_recv; - ibdev->ib_dev.create_cq = mlx4_ib_create_cq; - ibdev->ib_dev.destroy_cq = mlx4_ib_destroy_cq; - ibdev->ib_dev.poll_cq = mlx4_ib_poll_cq; - ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq; - ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr; - ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr; - ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr; - ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; - ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; - ibdev->ib_dev.process_mad = mlx4_ib_process_mad; - - if (init_node_data(ibdev)) - goto err_map; - - spin_lock_init(&ibdev->sm_lock); - mutex_init(&ibdev->cap_mask_mutex); - - if (ib_register_device(&ibdev->ib_dev)) - goto err_map; - - if (mlx4_ib_mad_init(ibdev)) - goto err_reg; - - return ibdev; - -err_reg: - ib_unregister_device(&ibdev->ib_dev); - -err_map: - iounmap(ibdev->uar_map); - -err_uar: - mlx4_uar_free(dev, &ibdev->priv_uar); - -err_pd: - mlx4_pd_free(dev, ibdev->priv_pdn); - -err_dealloc: - ib_dealloc_device(&ibdev->ib_dev); - - return NULL; -} - -static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) -{ - struct mlx4_ib_dev *ibdev = ibdev_ptr; - int p; - - for (p = 1; p <= dev->caps.num_ports; ++p) - mlx4_CLOSE_PORT(dev, p); - - mlx4_ib_mad_cleanup(ibdev); - ib_unregister_device(&ibdev->ib_dev); - iounmap(ibdev->uar_map); - mlx4_uar_free(dev, &ibdev->priv_uar); - mlx4_pd_free(dev, ibdev->priv_pdn); - ib_dealloc_device(&ibdev->ib_dev); -} - -static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, - enum mlx4_dev_event event, int subtype, - int port) -{ - struct ib_event ibev; - - switch (event) { - case MLX4_EVENT_TYPE_PORT_CHANGE: - ibev.event = subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ? - IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; - break; - - case MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR: - ibev.event = IB_EVENT_DEVICE_FATAL; - break; - - default: - return; - } - - ibev.device = ibdev_ptr; - ibev.element.port_num = port; - - ib_dispatch_event(&ibev); -} - -static struct mlx4_interface mlx4_ib_interface = { - .add = mlx4_ib_add, - .remove = mlx4_ib_remove, - .event = mlx4_ib_event -}; - -static int __init mlx4_ib_init(void) -{ - return mlx4_register_interface(&mlx4_ib_interface); -} - -static void __exit mlx4_ib_cleanup(void) -{ - mlx4_unregister_interface(&mlx4_ib_interface); -} - -module_init(mlx4_ib_init); -module_exit(mlx4_ib_cleanup); diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h deleted file mode 100644 index 93dac71f3230..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems. 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 MLX4_IB_H -#define MLX4_IB_H - -#include -#include - -#include -#include - -#include -#include - -enum { - MLX4_IB_DB_PER_PAGE = PAGE_SIZE / 4 -}; - -struct mlx4_ib_db_pgdir; -struct mlx4_ib_user_db_page; - -struct mlx4_ib_db { - __be32 *db; - union { - struct mlx4_ib_db_pgdir *pgdir; - struct mlx4_ib_user_db_page *user_page; - } u; - dma_addr_t dma; - int index; - int order; -}; - -struct mlx4_ib_ucontext { - struct ib_ucontext ibucontext; - struct mlx4_uar uar; - struct list_head db_page_list; - struct mutex db_page_mutex; -}; - -struct mlx4_ib_pd { - struct ib_pd ibpd; - u32 pdn; -}; - -struct mlx4_ib_cq_buf { - struct mlx4_buf buf; - struct mlx4_mtt mtt; -}; - -struct mlx4_ib_cq { - struct ib_cq ibcq; - struct mlx4_cq mcq; - struct mlx4_ib_cq_buf buf; - struct mlx4_ib_db db; - spinlock_t lock; - struct ib_umem *umem; -}; - -struct mlx4_ib_mr { - struct ib_mr ibmr; - struct mlx4_mr mmr; - struct ib_umem *umem; -}; - -struct mlx4_ib_wq { - u64 *wrid; - spinlock_t lock; - int max; - int max_gs; - int offset; - int wqe_shift; - unsigned head; - unsigned tail; -}; - -struct mlx4_ib_qp { - struct ib_qp ibqp; - struct mlx4_qp mqp; - struct mlx4_buf buf; - - struct mlx4_ib_db db; - struct mlx4_ib_wq rq; - - u32 doorbell_qpn; - __be32 sq_signal_bits; - struct mlx4_ib_wq sq; - - struct ib_umem *umem; - struct mlx4_mtt mtt; - int buf_size; - struct mutex mutex; - u8 port; - u8 alt_port; - u8 atomic_rd_en; - u8 resp_depth; - u8 state; -}; - -struct mlx4_ib_srq { - struct ib_srq ibsrq; - struct mlx4_srq msrq; - struct mlx4_buf buf; - struct mlx4_ib_db db; - u64 *wrid; - spinlock_t lock; - int head; - int tail; - u16 wqe_ctr; - struct ib_umem *umem; - struct mlx4_mtt mtt; - struct mutex mutex; -}; - -struct mlx4_ib_ah { - struct ib_ah ibah; - struct mlx4_av av; -}; - -struct mlx4_ib_dev { - struct ib_device ib_dev; - struct mlx4_dev *dev; - void __iomem *uar_map; - - struct list_head pgdir_list; - struct mutex pgdir_mutex; - - struct mlx4_uar priv_uar; - u32 priv_pdn; - MLX4_DECLARE_DOORBELL_LOCK(uar_lock); - - struct ib_mad_agent *send_agent[MLX4_MAX_PORTS][2]; - struct ib_ah *sm_ah[MLX4_MAX_PORTS]; - spinlock_t sm_lock; - - struct mutex cap_mask_mutex; -}; - -static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) -{ - return container_of(ibdev, struct mlx4_ib_dev, ib_dev); -} - -static inline struct mlx4_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext) -{ - return container_of(ibucontext, struct mlx4_ib_ucontext, ibucontext); -} - -static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd) -{ - return container_of(ibpd, struct mlx4_ib_pd, ibpd); -} - -static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq) -{ - return container_of(ibcq, struct mlx4_ib_cq, ibcq); -} - -static inline struct mlx4_ib_cq *to_mibcq(struct mlx4_cq *mcq) -{ - return container_of(mcq, struct mlx4_ib_cq, mcq); -} - -static inline struct mlx4_ib_mr *to_mmr(struct ib_mr *ibmr) -{ - return container_of(ibmr, struct mlx4_ib_mr, ibmr); -} - -static inline struct mlx4_ib_qp *to_mqp(struct ib_qp *ibqp) -{ - return container_of(ibqp, struct mlx4_ib_qp, ibqp); -} - -static inline struct mlx4_ib_qp *to_mibqp(struct mlx4_qp *mqp) -{ - return container_of(mqp, struct mlx4_ib_qp, mqp); -} - -static inline struct mlx4_ib_srq *to_msrq(struct ib_srq *ibsrq) -{ - return container_of(ibsrq, struct mlx4_ib_srq, ibsrq); -} - -static inline struct mlx4_ib_srq *to_mibsrq(struct mlx4_srq *msrq) -{ - return container_of(msrq, struct mlx4_ib_srq, msrq); -} - -static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah) -{ - return container_of(ibah, struct mlx4_ib_ah, ibah); -} - -int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order); -void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db); -int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, - struct mlx4_ib_db *db); -void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db); - -struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc); -int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, - struct ib_umem *umem); -struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int access_flags, - struct ib_udata *udata); -int mlx4_ib_dereg_mr(struct ib_mr *mr); - -struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, - struct ib_ucontext *context, - struct ib_udata *udata); -int mlx4_ib_destroy_cq(struct ib_cq *cq); -int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); -int mlx4_ib_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags); -void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq); -void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq); - -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); -int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr); -int mlx4_ib_destroy_ah(struct ib_ah *ah); - -struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *init_attr, - struct ib_udata *udata); -int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); -int mlx4_ib_destroy_srq(struct ib_srq *srq); -void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index); -int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr); - -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); -int mlx4_ib_destroy_qp(struct ib_qp *qp); -int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata); -int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, - struct ib_send_wr **bad_wr); -int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr); - -int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, - int port, struct ib_wc *in_wc, struct ib_grh *in_grh, - void *in_mad, void *response_mad); -int mlx4_ib_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); -int mlx4_ib_mad_init(struct mlx4_ib_dev *dev); -void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev); - -static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah) -{ - return !!(ah->av.g_slid & 0x80); -} - -#endif /* MLX4_IB_H */ diff --git a/trunk/drivers/infiniband/hw/mlx4/mr.c b/trunk/drivers/infiniband/hw/mlx4/mr.c deleted file mode 100644 index 85ae906f1d12..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mr.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" - -static u32 convert_access(int acc) -{ - return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX4_PERM_ATOMIC : 0) | - (acc & IB_ACCESS_REMOTE_WRITE ? MLX4_PERM_REMOTE_WRITE : 0) | - (acc & IB_ACCESS_REMOTE_READ ? MLX4_PERM_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? MLX4_PERM_LOCAL_WRITE : 0) | - MLX4_PERM_LOCAL_READ; -} - -struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc) -{ - struct mlx4_ib_mr *mr; - int err; - - mr = kmalloc(sizeof *mr, GFP_KERNEL); - if (!mr) - return ERR_PTR(-ENOMEM); - - err = mlx4_mr_alloc(to_mdev(pd->device)->dev, to_mpd(pd)->pdn, 0, - ~0ull, convert_access(acc), 0, 0, &mr->mmr); - if (err) - goto err_free; - - err = mlx4_mr_enable(to_mdev(pd->device)->dev, &mr->mmr); - if (err) - goto err_mr; - - mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; - mr->umem = NULL; - - return &mr->ibmr; - -err_mr: - mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); - -err_free: - kfree(mr); - - return ERR_PTR(err); -} - -int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, - struct ib_umem *umem) -{ - u64 *pages; - struct ib_umem_chunk *chunk; - int i, j, k; - int n; - int len; - int err = 0; - - pages = (u64 *) __get_free_page(GFP_KERNEL); - if (!pages) - return -ENOMEM; - - i = n = 0; - - list_for_each_entry(chunk, &umem->chunk_list, list) - for (j = 0; j < chunk->nmap; ++j) { - len = sg_dma_len(&chunk->page_list[j]) >> mtt->page_shift; - for (k = 0; k < len; ++k) { - pages[i++] = sg_dma_address(&chunk->page_list[j]) + - umem->page_size * k; - /* - * Be friendly to WRITE_MTT firmware - * command, and pass it chunks of - * appropriate size. - */ - if (i == PAGE_SIZE / sizeof (u64) - 2) { - err = mlx4_write_mtt(dev->dev, mtt, n, - i, pages); - if (err) - goto out; - n += i; - i = 0; - } - } - } - - if (i) - err = mlx4_write_mtt(dev->dev, mtt, n, i, pages); - -out: - free_page((unsigned long) pages); - return err; -} - -struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int access_flags, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_mr *mr; - int shift; - int err; - int n; - - mr = kmalloc(sizeof *mr, GFP_KERNEL); - if (!mr) - return ERR_PTR(-ENOMEM); - - mr->umem = ib_umem_get(pd->uobject->context, start, length, access_flags); - if (IS_ERR(mr->umem)) { - err = PTR_ERR(mr->umem); - goto err_free; - } - - n = ib_umem_page_count(mr->umem); - shift = ilog2(mr->umem->page_size); - - err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, virt_addr, length, - convert_access(access_flags), n, shift, &mr->mmr); - if (err) - goto err_umem; - - err = mlx4_ib_umem_write_mtt(dev, &mr->mmr.mtt, mr->umem); - if (err) - goto err_mr; - - err = mlx4_mr_enable(dev->dev, &mr->mmr); - if (err) - goto err_mr; - - mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; - - return &mr->ibmr; - -err_mr: - mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); - -err_umem: - ib_umem_release(mr->umem); - -err_free: - kfree(mr); - - return ERR_PTR(err); -} - -int mlx4_ib_dereg_mr(struct ib_mr *ibmr) -{ - struct mlx4_ib_mr *mr = to_mmr(ibmr); - - mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr); - if (mr->umem) - ib_umem_release(mr->umem); - kfree(mr); - - return 0; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c deleted file mode 100644 index 5cd706908450..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ /dev/null @@ -1,1294 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" -#include "user.h" - -enum { - MLX4_IB_ACK_REQ_FREQ = 8, -}; - -enum { - MLX4_IB_DEFAULT_SCHED_QUEUE = 0x83, - MLX4_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f -}; - -enum { - /* - * Largest possible UD header: send with GRH and immediate data. - */ - MLX4_IB_UD_HEADER_SIZE = 72 -}; - -struct mlx4_ib_sqp { - struct mlx4_ib_qp qp; - int pkey_index; - u32 qkey; - u32 send_psn; - struct ib_ud_header ud_header; - u8 header_buf[MLX4_IB_UD_HEADER_SIZE]; -}; - -static const __be32 mlx4_ib_opcode[] = { - [IB_WR_SEND] = __constant_cpu_to_be32(MLX4_OPCODE_SEND), - [IB_WR_SEND_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM), - [IB_WR_RDMA_WRITE] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE), - [IB_WR_RDMA_WRITE_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM), - [IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ), - [IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), - [IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), -}; - -static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) -{ - return container_of(mqp, struct mlx4_ib_sqp, qp); -} - -static int is_sqp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) -{ - return qp->mqp.qpn >= dev->dev->caps.sqp_start && - qp->mqp.qpn <= dev->dev->caps.sqp_start + 3; -} - -static int is_qp0(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) -{ - return qp->mqp.qpn >= dev->dev->caps.sqp_start && - qp->mqp.qpn <= dev->dev->caps.sqp_start + 1; -} - -static void *get_wqe(struct mlx4_ib_qp *qp, int offset) -{ - if (qp->buf.nbufs == 1) - return qp->buf.u.direct.buf + offset; - else - return qp->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void *get_recv_wqe(struct mlx4_ib_qp *qp, int n) -{ - return get_wqe(qp, qp->rq.offset + (n << qp->rq.wqe_shift)); -} - -static void *get_send_wqe(struct mlx4_ib_qp *qp, int n) -{ - return get_wqe(qp, qp->sq.offset + (n << qp->sq.wqe_shift)); -} - -static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type) -{ - struct ib_event event; - struct ib_qp *ibqp = &to_mibqp(qp)->ibqp; - - if (type == MLX4_EVENT_TYPE_PATH_MIG) - to_mibqp(qp)->port = to_mibqp(qp)->alt_port; - - if (ibqp->event_handler) { - event.device = ibqp->device; - event.element.qp = ibqp; - switch (type) { - case MLX4_EVENT_TYPE_PATH_MIG: - event.event = IB_EVENT_PATH_MIG; - break; - case MLX4_EVENT_TYPE_COMM_EST: - event.event = IB_EVENT_COMM_EST; - break; - case MLX4_EVENT_TYPE_SQ_DRAINED: - event.event = IB_EVENT_SQ_DRAINED; - break; - case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE: - event.event = IB_EVENT_QP_LAST_WQE_REACHED; - break; - case MLX4_EVENT_TYPE_WQ_CATAS_ERROR: - event.event = IB_EVENT_QP_FATAL; - break; - case MLX4_EVENT_TYPE_PATH_MIG_FAILED: - event.event = IB_EVENT_PATH_MIG_ERR; - break; - case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - event.event = IB_EVENT_QP_REQ_ERR; - break; - case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR: - event.event = IB_EVENT_QP_ACCESS_ERR; - break; - default: - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on QP %06x\n", type, qp->qpn); - return; - } - - ibqp->event_handler(&event, ibqp->qp_context); - } -} - -static int send_wqe_overhead(enum ib_qp_type type) -{ - /* - * UD WQEs must have a datagram segment. - * RC and UC WQEs might have a remote address segment. - * MLX WQEs need two extra inline data segments (for the UD - * header and space for the ICRC). - */ - switch (type) { - case IB_QPT_UD: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_datagram_seg); - case IB_QPT_UC: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_raddr_seg); - case IB_QPT_RC: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_atomic_seg) + - sizeof (struct mlx4_wqe_raddr_seg); - case IB_QPT_SMI: - case IB_QPT_GSI: - return sizeof (struct mlx4_wqe_ctrl_seg) + - ALIGN(MLX4_IB_UD_HEADER_SIZE + - sizeof (struct mlx4_wqe_inline_seg), - sizeof (struct mlx4_wqe_data_seg)) + - ALIGN(4 + - sizeof (struct mlx4_wqe_inline_seg), - sizeof (struct mlx4_wqe_data_seg)); - default: - return sizeof (struct mlx4_wqe_ctrl_seg); - } -} - -static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, - enum ib_qp_type type, struct mlx4_ib_qp *qp) -{ - /* Sanity check QP size before proceeding */ - if (cap->max_send_wr > dev->dev->caps.max_wqes || - cap->max_recv_wr > dev->dev->caps.max_wqes || - cap->max_send_sge > dev->dev->caps.max_sq_sg || - cap->max_recv_sge > dev->dev->caps.max_rq_sg || - cap->max_inline_data + send_wqe_overhead(type) + - sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz) - return -EINVAL; - - /* - * For MLX transport we need 2 extra S/G entries: - * one for the header and one for the checksum at the end - */ - if ((type == IB_QPT_SMI || type == IB_QPT_GSI) && - cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg) - return -EINVAL; - - qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0; - qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 0; - - qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge * - sizeof (struct mlx4_wqe_data_seg))); - qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg); - - qp->sq.wqe_shift = ilog2(roundup_pow_of_two(max(cap->max_send_sge * - sizeof (struct mlx4_wqe_data_seg), - cap->max_inline_data + - sizeof (struct mlx4_wqe_inline_seg)) + - send_wqe_overhead(type))); - qp->sq.max_gs = ((1 << qp->sq.wqe_shift) - send_wqe_overhead(type)) / - sizeof (struct mlx4_wqe_data_seg); - - qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) + - (qp->sq.max << qp->sq.wqe_shift); - if (qp->rq.wqe_shift > qp->sq.wqe_shift) { - qp->rq.offset = 0; - qp->sq.offset = qp->rq.max << qp->rq.wqe_shift; - } else { - qp->rq.offset = qp->sq.max << qp->sq.wqe_shift; - qp->sq.offset = 0; - } - - cap->max_send_wr = qp->sq.max; - cap->max_recv_wr = qp->rq.max; - cap->max_send_sge = qp->sq.max_gs; - cap->max_recv_sge = qp->rq.max_gs; - cap->max_inline_data = (1 << qp->sq.wqe_shift) - send_wqe_overhead(type) - - sizeof (struct mlx4_wqe_inline_seg); - - return 0; -} - -static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp) -{ - struct mlx4_wqe_ctrl_seg *ctrl; - int err; - int i; - - mutex_init(&qp->mutex); - spin_lock_init(&qp->sq.lock); - spin_lock_init(&qp->rq.lock); - - qp->state = IB_QPS_RESET; - qp->atomic_rd_en = 0; - qp->resp_depth = 0; - - qp->rq.head = 0; - qp->rq.tail = 0; - qp->sq.head = 0; - qp->sq.tail = 0; - - err = set_qp_size(dev, &init_attr->cap, init_attr->qp_type, qp); - if (err) - goto err; - - if (pd->uobject) { - struct mlx4_ib_create_qp ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err; - } - - qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, - qp->buf_size, 0); - if (IS_ERR(qp->umem)) { - err = PTR_ERR(qp->umem); - goto err; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(qp->umem), - ilog2(qp->umem->page_size), &qp->mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &qp->mtt, qp->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context), - ucmd.db_addr, &qp->db); - if (err) - goto err_mtt; - } else { - err = mlx4_ib_db_alloc(dev, &qp->db, 0); - if (err) - goto err; - - *qp->db.db = 0; - - if (mlx4_buf_alloc(dev->dev, qp->buf_size, PAGE_SIZE * 2, &qp->buf)) { - err = -ENOMEM; - goto err_db; - } - - err = mlx4_mtt_init(dev->dev, qp->buf.npages, qp->buf.page_shift, - &qp->mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &qp->mtt, &qp->buf); - if (err) - goto err_mtt; - - for (i = 0; i < qp->sq.max; ++i) { - ctrl = get_send_wqe(qp, i); - ctrl->owner_opcode = cpu_to_be32(1 << 31); - } - - qp->sq.wrid = kmalloc(qp->sq.max * sizeof (u64), GFP_KERNEL); - qp->rq.wrid = kmalloc(qp->rq.max * sizeof (u64), GFP_KERNEL); - - if (!qp->sq.wrid || !qp->rq.wrid) { - err = -ENOMEM; - goto err_wrid; - } - - /* We don't support inline sends for kernel QPs (yet) */ - init_attr->cap.max_inline_data = 0; - } - - err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp); - if (err) - goto err_wrid; - - /* - * Hardware wants QPN written in big-endian order (after - * shifting) for send doorbell. Precompute this value to save - * a little bit when posting sends. - */ - qp->doorbell_qpn = swab32(qp->mqp.qpn << 8); - - if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) - qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE); - else - qp->sq_signal_bits = 0; - - qp->mqp.event = mlx4_ib_qp_event; - - return 0; - -err_wrid: - if (pd->uobject) - mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db); - else { - kfree(qp->sq.wrid); - kfree(qp->rq.wrid); - } - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &qp->mtt); - -err_buf: - if (pd->uobject) - ib_umem_release(qp->umem); - else - mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); - -err_db: - if (!pd->uobject) - mlx4_ib_db_free(dev, &qp->db); - -err: - return err; -} - -static enum mlx4_qp_state to_mlx4_state(enum ib_qp_state state) -{ - switch (state) { - case IB_QPS_RESET: return MLX4_QP_STATE_RST; - case IB_QPS_INIT: return MLX4_QP_STATE_INIT; - case IB_QPS_RTR: return MLX4_QP_STATE_RTR; - case IB_QPS_RTS: return MLX4_QP_STATE_RTS; - case IB_QPS_SQD: return MLX4_QP_STATE_SQD; - case IB_QPS_SQE: return MLX4_QP_STATE_SQER; - case IB_QPS_ERR: return MLX4_QP_STATE_ERR; - default: return -1; - } -} - -static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_lock_irq(&send_cq->lock); - else if (send_cq->mcq.cqn < recv_cq->mcq.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 mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_unlock_irq(&send_cq->lock); - else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); - } else { - spin_unlock(&send_cq->lock); - spin_unlock_irq(&recv_cq->lock); - } -} - -static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, - int is_user) -{ - struct mlx4_ib_cq *send_cq, *recv_cq; - - if (qp->state != IB_QPS_RESET) - if (mlx4_qp_modify(dev->dev, NULL, to_mlx4_state(qp->state), - MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp)) - printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n", - qp->mqp.qpn); - - send_cq = to_mcq(qp->ibqp.send_cq); - recv_cq = to_mcq(qp->ibqp.recv_cq); - - mlx4_ib_lock_cqs(send_cq, recv_cq); - - if (!is_user) { - __mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn, - qp->ibqp.srq ? to_msrq(qp->ibqp.srq): NULL); - if (send_cq != recv_cq) - __mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL); - } - - mlx4_qp_remove(dev->dev, &qp->mqp); - - mlx4_ib_unlock_cqs(send_cq, recv_cq); - - mlx4_qp_free(dev->dev, &qp->mqp); - mlx4_mtt_cleanup(dev->dev, &qp->mtt); - - if (is_user) { - mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context), - &qp->db); - ib_umem_release(qp->umem); - } else { - kfree(qp->sq.wrid); - kfree(qp->rq.wrid); - mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); - mlx4_ib_db_free(dev, &qp->db); - } -} - -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_sqp *sqp; - struct mlx4_ib_qp *qp; - int err; - - switch (init_attr->qp_type) { - case IB_QPT_RC: - case IB_QPT_UC: - case IB_QPT_UD: - { - qp = kmalloc(sizeof *qp, GFP_KERNEL); - if (!qp) - return ERR_PTR(-ENOMEM); - - err = create_qp_common(dev, pd, init_attr, udata, 0, qp); - if (err) { - kfree(qp); - return ERR_PTR(err); - } - - qp->ibqp.qp_num = qp->mqp.qpn; - - break; - } - case IB_QPT_SMI: - case IB_QPT_GSI: - { - /* Userspace is not allowed to create special QPs: */ - if (pd->uobject) - return ERR_PTR(-EINVAL); - - sqp = kmalloc(sizeof *sqp, GFP_KERNEL); - if (!sqp) - return ERR_PTR(-ENOMEM); - - qp = &sqp->qp; - - err = create_qp_common(dev, pd, init_attr, udata, - dev->dev->caps.sqp_start + - (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) + - init_attr->port_num - 1, - qp); - if (err) { - kfree(sqp); - return ERR_PTR(err); - } - - qp->port = init_attr->port_num; - qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1; - - break; - } - default: - /* Don't support raw QPs */ - return ERR_PTR(-EINVAL); - } - - return &qp->ibqp; -} - -int mlx4_ib_destroy_qp(struct ib_qp *qp) -{ - struct mlx4_ib_dev *dev = to_mdev(qp->device); - struct mlx4_ib_qp *mqp = to_mqp(qp); - - if (is_qp0(dev, mqp)) - mlx4_CLOSE_PORT(dev->dev, mqp->port); - - destroy_qp_common(dev, mqp, !!qp->pd->uobject); - - if (is_sqp(dev, mqp)) - kfree(to_msqp(mqp)); - else - kfree(mqp); - - return 0; -} - -static void init_port(struct mlx4_ib_dev *dev, int port) -{ - struct mlx4_init_port_param param; - int err; - - memset(¶m, 0, sizeof param); - - param.port_width_cap = dev->dev->caps.port_width_cap; - param.vl_cap = dev->dev->caps.vl_cap; - param.mtu = ib_mtu_enum_to_int(dev->dev->caps.mtu_cap); - param.max_gid = dev->dev->caps.gid_table_len; - param.max_pkey = dev->dev->caps.pkey_table_len; - - err = mlx4_INIT_PORT(dev->dev, ¶m, port); - if (err) - printk(KERN_WARNING "INIT_PORT failed, return code %d.\n", err); -} - -static int to_mlx4_st(enum ib_qp_type type) -{ - switch (type) { - case IB_QPT_RC: return MLX4_QP_ST_RC; - case IB_QPT_UC: return MLX4_QP_ST_UC; - case IB_QPT_UD: return MLX4_QP_ST_UD; - case IB_QPT_SMI: - case IB_QPT_GSI: return MLX4_QP_ST_MLX; - default: return -1; - } -} - -static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, struct ib_qp_attr *attr, - int attr_mask) -{ - u8 dest_rd_atomic; - u32 access_flags; - u32 hw_access_flags = 0; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - dest_rd_atomic = attr->max_dest_rd_atomic; - else - dest_rd_atomic = qp->resp_depth; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - access_flags = attr->qp_access_flags; - else - access_flags = qp->atomic_rd_en; - - if (!dest_rd_atomic) - access_flags &= IB_ACCESS_REMOTE_WRITE; - - if (access_flags & IB_ACCESS_REMOTE_READ) - hw_access_flags |= MLX4_QP_BIT_RRE; - if (access_flags & IB_ACCESS_REMOTE_ATOMIC) - hw_access_flags |= MLX4_QP_BIT_RAE; - if (access_flags & IB_ACCESS_REMOTE_WRITE) - hw_access_flags |= MLX4_QP_BIT_RWE; - - return cpu_to_be32(hw_access_flags); -} - -static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, struct ib_qp_attr *attr, - int attr_mask) -{ - if (attr_mask & IB_QP_PKEY_INDEX) - sqp->pkey_index = attr->pkey_index; - if (attr_mask & IB_QP_QKEY) - sqp->qkey = attr->qkey; - if (attr_mask & IB_QP_SQ_PSN) - sqp->send_psn = attr->sq_psn; -} - -static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port) -{ - path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6); -} - -static int mlx4_set_path(struct mlx4_ib_dev *dev, struct ib_ah_attr *ah, - struct mlx4_qp_path *path, u8 port) -{ - path->grh_mylmc = ah->src_path_bits & 0x7f; - path->rlid = cpu_to_be16(ah->dlid); - if (ah->static_rate) { - path->static_rate = ah->static_rate + MLX4_STAT_RATE_OFFSET; - while (path->static_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && - !(1 << path->static_rate & dev->dev->caps.stat_rate_support)) - --path->static_rate; - } else - path->static_rate = 0; - path->counter_index = 0xff; - - if (ah->ah_flags & IB_AH_GRH) { - if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len) { - printk(KERN_ERR "sgid_index (%u) too large. max is %d\n", - ah->grh.sgid_index, dev->dev->caps.gid_table_len - 1); - return -1; - } - - path->grh_mylmc |= 1 << 7; - path->mgid_index = ah->grh.sgid_index; - path->hop_limit = ah->grh.hop_limit; - path->tclass_flowlabel = - cpu_to_be32((ah->grh.traffic_class << 20) | - (ah->grh.flow_label)); - memcpy(path->rgid, ah->grh.dgid.raw, 16); - } - - path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | - ((port - 1) << 6) | ((ah->sl & 0xf) << 2); - - return 0; -} - -int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibqp->device); - struct mlx4_ib_qp *qp = to_mqp(ibqp); - struct mlx4_qp_context *context; - enum mlx4_qp_optpar optpar = 0; - enum ib_qp_state cur_state, new_state; - int sqd_event; - int err = -EINVAL; - - context = kzalloc(sizeof *context, GFP_KERNEL); - if (!context) - return -ENOMEM; - - mutex_lock(&qp->mutex); - - cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; - new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; - - if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) - goto out; - - if ((attr_mask & IB_QP_PKEY_INDEX) && - attr->pkey_index >= dev->dev->caps.pkey_table_len) { - goto out; - } - - if ((attr_mask & IB_QP_PORT) && - (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) { - goto out; - } - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && - attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) { - goto out; - } - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && - attr->max_dest_rd_atomic > 1 << dev->dev->caps.max_qp_dest_rdma) { - goto out; - } - - context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) | - (to_mlx4_st(ibqp->qp_type) << 16)); - context->flags |= cpu_to_be32(1 << 8); /* DE? */ - - if (!(attr_mask & IB_QP_PATH_MIG_STATE)) - context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11); - else { - optpar |= MLX4_QP_OPTPAR_PM_STATE; - switch (attr->path_mig_state) { - case IB_MIG_MIGRATED: - context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11); - break; - case IB_MIG_REARM: - context->flags |= cpu_to_be32(MLX4_QP_PM_REARM << 11); - break; - case IB_MIG_ARMED: - context->flags |= cpu_to_be32(MLX4_QP_PM_ARMED << 11); - break; - } - } - - if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI || - ibqp->qp_type == IB_QPT_UD) - context->mtu_msgmax = (IB_MTU_4096 << 5) | 11; - else if (attr_mask & IB_QP_PATH_MTU) { - if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_4096) { - printk(KERN_ERR "path MTU (%u) is invalid\n", - attr->path_mtu); - return -EINVAL; - } - context->mtu_msgmax = (attr->path_mtu << 5) | 31; - } - - if (qp->rq.max) - context->rq_size_stride = ilog2(qp->rq.max) << 3; - context->rq_size_stride |= qp->rq.wqe_shift - 4; - - if (qp->sq.max) - context->sq_size_stride = ilog2(qp->sq.max) << 3; - context->sq_size_stride |= qp->sq.wqe_shift - 4; - - if (qp->ibqp.uobject) - context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index); - else - context->usr_page = cpu_to_be32(dev->priv_uar.index); - - if (attr_mask & IB_QP_DEST_QPN) - context->remote_qpn = cpu_to_be32(attr->dest_qp_num); - - if (attr_mask & IB_QP_PORT) { - if (cur_state == IB_QPS_SQD && new_state == IB_QPS_SQD && - !(attr_mask & IB_QP_AV)) { - mlx4_set_sched(&context->pri_path, attr->port_num); - optpar |= MLX4_QP_OPTPAR_SCHED_QUEUE; - } - } - - if (attr_mask & IB_QP_PKEY_INDEX) { - context->pri_path.pkey_index = attr->pkey_index; - optpar |= MLX4_QP_OPTPAR_PKEY_INDEX; - } - - if (attr_mask & IB_QP_RNR_RETRY) { - context->params1 |= cpu_to_be32(attr->rnr_retry << 13); - optpar |= MLX4_QP_OPTPAR_RNR_RETRY; - } - - if (attr_mask & IB_QP_AV) { - if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path, - attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) { - err = -EINVAL; - goto out; - } - - optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH | - MLX4_QP_OPTPAR_SCHED_QUEUE); - } - - if (attr_mask & IB_QP_TIMEOUT) { - context->pri_path.ackto = attr->timeout << 3; - optpar |= MLX4_QP_OPTPAR_ACK_TIMEOUT; - } - - if (attr_mask & IB_QP_ALT_PATH) { - if (attr->alt_pkey_index >= dev->dev->caps.pkey_table_len) - return -EINVAL; - - if (attr->alt_port_num == 0 || - attr->alt_port_num > dev->dev->caps.num_ports) - return -EINVAL; - - if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path, - attr->alt_port_num)) - return -EINVAL; - - context->alt_path.pkey_index = attr->alt_pkey_index; - context->alt_path.ackto = attr->alt_timeout << 3; - optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH; - } - - context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); - context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); - if (attr_mask & IB_QP_RETRY_CNT) { - context->params1 |= cpu_to_be32(attr->retry_cnt << 16); - optpar |= MLX4_QP_OPTPAR_RETRY_COUNT; - } - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { - if (attr->max_rd_atomic) - context->params1 |= - cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21); - optpar |= MLX4_QP_OPTPAR_SRA_MAX; - } - - if (attr_mask & IB_QP_SQ_PSN) - context->next_send_psn = cpu_to_be32(attr->sq_psn); - - context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn); - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { - if (attr->max_dest_rd_atomic) - context->params2 |= - cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21); - optpar |= MLX4_QP_OPTPAR_RRA_MAX; - } - - if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) { - context->params2 |= to_mlx4_access_flags(qp, attr, attr_mask); - optpar |= MLX4_QP_OPTPAR_RWE | MLX4_QP_OPTPAR_RRE | MLX4_QP_OPTPAR_RAE; - } - - if (ibqp->srq) - context->params2 |= cpu_to_be32(MLX4_QP_BIT_RIC); - - if (attr_mask & IB_QP_MIN_RNR_TIMER) { - context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24); - optpar |= MLX4_QP_OPTPAR_RNR_TIMEOUT; - } - if (attr_mask & IB_QP_RQ_PSN) - context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn); - - context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn); - - if (attr_mask & IB_QP_QKEY) { - context->qkey = cpu_to_be32(attr->qkey); - optpar |= MLX4_QP_OPTPAR_Q_KEY; - } - - if (ibqp->srq) - context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn); - - if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) - context->db_rec_addr = cpu_to_be64(qp->db.dma); - - if (cur_state == IB_QPS_INIT && - new_state == IB_QPS_RTR && - (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI || - ibqp->qp_type == IB_QPT_UD)) { - context->pri_path.sched_queue = (qp->port - 1) << 6; - if (is_qp0(dev, qp)) - context->pri_path.sched_queue |= MLX4_IB_DEFAULT_QP0_SCHED_QUEUE; - else - context->pri_path.sched_queue |= MLX4_IB_DEFAULT_SCHED_QUEUE; - } - - if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD && - attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify) - sqd_event = 1; - else - sqd_event = 0; - - err = mlx4_qp_modify(dev->dev, &qp->mtt, to_mlx4_state(cur_state), - to_mlx4_state(new_state), context, optpar, - sqd_event, &qp->mqp); - if (err) - goto out; - - qp->state = new_state; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - qp->atomic_rd_en = attr->qp_access_flags; - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - qp->resp_depth = attr->max_dest_rd_atomic; - if (attr_mask & IB_QP_PORT) - qp->port = attr->port_num; - if (attr_mask & IB_QP_ALT_PATH) - qp->alt_port = attr->alt_port_num; - - if (is_sqp(dev, qp)) - store_sqp_attrs(to_msqp(qp), attr, attr_mask); - - /* - * If we moved QP0 to RTR, bring the IB link up; if we moved - * QP0 to RESET or ERROR, bring the link back down. - */ - if (is_qp0(dev, qp)) { - if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR) - init_port(dev, qp->port); - - if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR && - (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR)) - mlx4_CLOSE_PORT(dev->dev, qp->port); - } - - /* - * If we moved a kernel QP to RESET, clean up all old CQ - * entries and reinitialize the QP. - */ - if (new_state == IB_QPS_RESET && !ibqp->uobject) { - mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn, - ibqp->srq ? to_msrq(ibqp->srq): NULL); - if (ibqp->send_cq != ibqp->recv_cq) - mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL); - - qp->rq.head = 0; - qp->rq.tail = 0; - qp->sq.head = 0; - qp->sq.tail = 0; - *qp->db.db = 0; - } - -out: - mutex_unlock(&qp->mutex); - kfree(context); - return err; -} - -static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, - void *wqe) -{ - struct ib_device *ib_dev = &to_mdev(sqp->qp.ibqp.device)->ib_dev; - struct mlx4_wqe_mlx_seg *mlx = wqe; - struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; - struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); - u16 pkey; - int send_size; - int header_size; - int i; - - send_size = 0; - for (i = 0; i < wr->num_sge; ++i) - send_size += wr->sg_list[i].length; - - ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), &sqp->ud_header); - - sqp->ud_header.lrh.service_level = - be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28; - sqp->ud_header.lrh.destination_lid = ah->av.dlid; - sqp->ud_header.lrh.source_lid = cpu_to_be16(ah->av.g_slid & 0x7f); - if (mlx4_ib_ah_grh_present(ah)) { - sqp->ud_header.grh.traffic_class = - (be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff; - sqp->ud_header.grh.flow_label = - ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff); - ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24, - ah->av.gid_index, &sqp->ud_header.grh.source_gid); - memcpy(sqp->ud_header.grh.destination_gid.raw, - ah->av.dgid, 16); - } - - mlx->flags &= cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE); - mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) | - (sqp->ud_header.lrh.destination_lid == - IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) | - (sqp->ud_header.lrh.service_level << 8)); - mlx->rlid = sqp->ud_header.lrh.destination_lid; - - switch (wr->opcode) { - case IB_WR_SEND: - sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY; - sqp->ud_header.immediate_present = 0; - break; - case IB_WR_SEND_WITH_IMM: - sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE; - sqp->ud_header.immediate_present = 1; - sqp->ud_header.immediate_data = wr->imm_data; - break; - default: - return -EINVAL; - } - - sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0; - if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE) - sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE; - sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED); - if (!sqp->qp.ibqp.qp_num) - ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey); - else - ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->wr.ud.pkey_index, &pkey); - sqp->ud_header.bth.pkey = cpu_to_be16(pkey); - sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn); - sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1)); - sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ? - sqp->qkey : wr->wr.ud.remote_qkey); - sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num); - - header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf); - - if (0) { - printk(KERN_ERR "built UD header of size %d:\n", header_size); - for (i = 0; i < header_size / 4; ++i) { - if (i % 8 == 0) - printk(" [%02x] ", i * 4); - printk(" %08x", - be32_to_cpu(((__be32 *) sqp->header_buf)[i])); - if ((i + 1) % 8 == 0) - printk("\n"); - } - printk("\n"); - } - - inl->byte_count = cpu_to_be32(1 << 31 | header_size); - memcpy(inl + 1, sqp->header_buf, header_size); - - return ALIGN(sizeof (struct mlx4_wqe_inline_seg) + header_size, 16); -} - -static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq) -{ - unsigned cur; - struct mlx4_ib_cq *cq; - - cur = wq->head - wq->tail; - if (likely(cur + nreq < wq->max)) - return 0; - - cq = to_mcq(ib_cq); - spin_lock(&cq->lock); - cur = wq->head - wq->tail; - spin_unlock(&cq->lock); - - return cur + nreq >= wq->max; -} - -int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, - struct ib_send_wr **bad_wr) -{ - struct mlx4_ib_qp *qp = to_mqp(ibqp); - void *wqe; - struct mlx4_wqe_ctrl_seg *ctrl; - unsigned long flags; - int nreq; - int err = 0; - int ind; - int size; - int i; - - spin_lock_irqsave(&qp->rq.lock, flags); - - ind = qp->sq.head; - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (mlx4_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) { - err = -ENOMEM; - *bad_wr = wr; - goto out; - } - - if (unlikely(wr->num_sge > qp->sq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - goto out; - } - - ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.max - 1)); - qp->sq.wrid[ind & (qp->sq.max - 1)] = wr->wr_id; - - ctrl->srcrb_flags = - (wr->send_flags & IB_SEND_SIGNALED ? - cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) : 0) | - (wr->send_flags & IB_SEND_SOLICITED ? - cpu_to_be32(MLX4_WQE_CTRL_SOLICITED) : 0) | - qp->sq_signal_bits; - - if (wr->opcode == IB_WR_SEND_WITH_IMM || - wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) - ctrl->imm = wr->imm_data; - else - ctrl->imm = 0; - - wqe += sizeof *ctrl; - size = sizeof *ctrl / 16; - - switch (ibqp->qp_type) { - case IB_QPT_RC: - case IB_QPT_UC: - switch (wr->opcode) { - case IB_WR_ATOMIC_CMP_AND_SWP: - case IB_WR_ATOMIC_FETCH_AND_ADD: - ((struct mlx4_wqe_raddr_seg *) wqe)->raddr = - cpu_to_be64(wr->wr.atomic.remote_addr); - ((struct mlx4_wqe_raddr_seg *) wqe)->rkey = - cpu_to_be32(wr->wr.atomic.rkey); - ((struct mlx4_wqe_raddr_seg *) wqe)->reserved = 0; - - wqe += sizeof (struct mlx4_wqe_raddr_seg); - - if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) { - ((struct mlx4_wqe_atomic_seg *) wqe)->swap_add = - cpu_to_be64(wr->wr.atomic.swap); - ((struct mlx4_wqe_atomic_seg *) wqe)->compare = - cpu_to_be64(wr->wr.atomic.compare_add); - } else { - ((struct mlx4_wqe_atomic_seg *) wqe)->swap_add = - cpu_to_be64(wr->wr.atomic.compare_add); - ((struct mlx4_wqe_atomic_seg *) wqe)->compare = 0; - } - - wqe += sizeof (struct mlx4_wqe_atomic_seg); - size += (sizeof (struct mlx4_wqe_raddr_seg) + - sizeof (struct mlx4_wqe_atomic_seg)) / 16; - - break; - - case IB_WR_RDMA_READ: - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - ((struct mlx4_wqe_raddr_seg *) wqe)->raddr = - cpu_to_be64(wr->wr.rdma.remote_addr); - ((struct mlx4_wqe_raddr_seg *) wqe)->rkey = - cpu_to_be32(wr->wr.rdma.rkey); - ((struct mlx4_wqe_raddr_seg *) wqe)->reserved = 0; - - wqe += sizeof (struct mlx4_wqe_raddr_seg); - size += sizeof (struct mlx4_wqe_raddr_seg) / 16; - - break; - - default: - /* No extra segments required for sends */ - break; - } - break; - - case IB_QPT_UD: - memcpy(((struct mlx4_wqe_datagram_seg *) wqe)->av, - &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); - ((struct mlx4_wqe_datagram_seg *) wqe)->dqpn = - cpu_to_be32(wr->wr.ud.remote_qpn); - ((struct mlx4_wqe_datagram_seg *) wqe)->qkey = - cpu_to_be32(wr->wr.ud.remote_qkey); - - wqe += sizeof (struct mlx4_wqe_datagram_seg); - size += sizeof (struct mlx4_wqe_datagram_seg) / 16; - break; - - case IB_QPT_SMI: - case IB_QPT_GSI: - err = build_mlx_header(to_msqp(qp), wr, ctrl); - if (err < 0) { - *bad_wr = wr; - goto out; - } - wqe += err; - size += err / 16; - - err = 0; - break; - - default: - break; - } - - for (i = 0; i < wr->num_sge; ++i) { - ((struct mlx4_wqe_data_seg *) wqe)->byte_count = - cpu_to_be32(wr->sg_list[i].length); - ((struct mlx4_wqe_data_seg *) wqe)->lkey = - cpu_to_be32(wr->sg_list[i].lkey); - ((struct mlx4_wqe_data_seg *) wqe)->addr = - cpu_to_be64(wr->sg_list[i].addr); - - wqe += sizeof (struct mlx4_wqe_data_seg); - size += sizeof (struct mlx4_wqe_data_seg) / 16; - } - - /* Add one more inline data segment for ICRC for MLX sends */ - if (qp->ibqp.qp_type == IB_QPT_SMI || qp->ibqp.qp_type == IB_QPT_GSI) { - ((struct mlx4_wqe_inline_seg *) wqe)->byte_count = - cpu_to_be32((1 << 31) | 4); - ((u32 *) wqe)[1] = 0; - wqe += sizeof (struct mlx4_wqe_data_seg); - size += sizeof (struct mlx4_wqe_data_seg) / 16; - } - - ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ? - MLX4_WQE_CTRL_FENCE : 0) | size; - - /* - * Make sure descriptor is fully written before - * setting ownership bit (because HW can start - * executing as soon as we do). - */ - wmb(); - - if (wr->opcode < 0 || wr->opcode > ARRAY_SIZE(mlx4_ib_opcode)) { - err = -EINVAL; - goto out; - } - - ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] | - (ind & qp->sq.max ? cpu_to_be32(1 << 31) : 0); - - ++ind; - } - -out: - if (likely(nreq)) { - qp->sq.head += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - writel(qp->doorbell_qpn, - to_mdev(ibqp->device)->uar_map + MLX4_SEND_DOORBELL); - - /* - * Make sure doorbells don't leak out of SQ spinlock - * and reach the HCA out of order. - */ - mmiowb(); - } - - spin_unlock_irqrestore(&qp->rq.lock, flags); - - return err; -} - -int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct mlx4_ib_qp *qp = to_mqp(ibqp); - struct mlx4_wqe_data_seg *scat; - unsigned long flags; - int err = 0; - int nreq; - int ind; - int i; - - spin_lock_irqsave(&qp->rq.lock, flags); - - ind = qp->rq.head & (qp->rq.max - 1); - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) { - err = -ENOMEM; - *bad_wr = wr; - goto out; - } - - if (unlikely(wr->num_sge > qp->rq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - goto out; - } - - scat = get_recv_wqe(qp, ind); - - for (i = 0; i < wr->num_sge; ++i) { - scat[i].byte_count = cpu_to_be32(wr->sg_list[i].length); - scat[i].lkey = cpu_to_be32(wr->sg_list[i].lkey); - scat[i].addr = cpu_to_be64(wr->sg_list[i].addr); - } - - if (i < qp->rq.max_gs) { - scat[i].byte_count = 0; - scat[i].lkey = cpu_to_be32(MLX4_INVALID_LKEY); - scat[i].addr = 0; - } - - qp->rq.wrid[ind] = wr->wr_id; - - ind = (ind + 1) & (qp->rq.max - 1); - } - -out: - if (likely(nreq)) { - qp->rq.head += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff); - } - - spin_unlock_irqrestore(&qp->rq.lock, flags); - - return err; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/srq.c b/trunk/drivers/infiniband/hw/mlx4/srq.c deleted file mode 100644 index 42ab4a801d6a..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/srq.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4_ib.h" -#include "user.h" - -static void *get_wqe(struct mlx4_ib_srq *srq, int n) -{ - int offset = n << srq->msrq.wqe_shift; - - if (srq->buf.nbufs == 1) - return srq->buf.u.direct.buf + offset; - else - return srq->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void mlx4_ib_srq_event(struct mlx4_srq *srq, enum mlx4_event type) -{ - struct ib_event event; - struct ib_srq *ibsrq = &to_mibsrq(srq)->ibsrq; - - if (ibsrq->event_handler) { - event.device = ibsrq->device; - event.element.srq = ibsrq; - switch (type) { - case MLX4_EVENT_TYPE_SRQ_LIMIT: - event.event = IB_EVENT_SRQ_LIMIT_REACHED; - break; - case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - event.event = IB_EVENT_SRQ_ERR; - break; - default: - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on SRQ %06x\n", type, srq->srqn); - return; - } - - ibsrq->event_handler(&event, ibsrq->srq_context); - } -} - -struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *init_attr, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_srq *srq; - struct mlx4_wqe_srq_next_seg *next; - int desc_size; - int buf_size; - int err; - int i; - - /* Sanity check SRQ size before proceeding */ - if (init_attr->attr.max_wr >= dev->dev->caps.max_srq_wqes || - init_attr->attr.max_sge > dev->dev->caps.max_srq_sge) - return ERR_PTR(-EINVAL); - - srq = kmalloc(sizeof *srq, GFP_KERNEL); - if (!srq) - return ERR_PTR(-ENOMEM); - - mutex_init(&srq->mutex); - spin_lock_init(&srq->lock); - srq->msrq.max = roundup_pow_of_two(init_attr->attr.max_wr + 1); - srq->msrq.max_gs = init_attr->attr.max_sge; - - desc_size = max(32UL, - roundup_pow_of_two(sizeof (struct mlx4_wqe_srq_next_seg) + - srq->msrq.max_gs * - sizeof (struct mlx4_wqe_data_seg))); - srq->msrq.wqe_shift = ilog2(desc_size); - - buf_size = srq->msrq.max * desc_size; - - if (pd->uobject) { - struct mlx4_ib_create_srq ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err_srq; - } - - srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, - buf_size, 0); - if (IS_ERR(srq->umem)) { - err = PTR_ERR(srq->umem); - goto err_srq; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(srq->umem), - ilog2(srq->umem->page_size), &srq->mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &srq->mtt, srq->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context), - ucmd.db_addr, &srq->db); - if (err) - goto err_mtt; - } else { - err = mlx4_ib_db_alloc(dev, &srq->db, 0); - if (err) - goto err_srq; - - *srq->db.db = 0; - - if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &srq->buf)) { - err = -ENOMEM; - goto err_db; - } - - srq->head = 0; - srq->tail = srq->msrq.max - 1; - srq->wqe_ctr = 0; - - for (i = 0; i < srq->msrq.max; ++i) { - next = get_wqe(srq, i); - next->next_wqe_index = - cpu_to_be16((i + 1) & (srq->msrq.max - 1)); - } - - err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift, - &srq->mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &srq->mtt, &srq->buf); - if (err) - goto err_mtt; - - srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL); - if (!srq->wrid) { - err = -ENOMEM; - goto err_mtt; - } - } - - err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt, - srq->db.dma, &srq->msrq); - if (err) - goto err_wrid; - - srq->msrq.event = mlx4_ib_srq_event; - - if (pd->uobject) - if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) { - err = -EFAULT; - goto err_wrid; - } - - init_attr->attr.max_wr = srq->msrq.max - 1; - - return &srq->ibsrq; - -err_wrid: - if (pd->uobject) - mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db); - else - kfree(srq->wrid); - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &srq->mtt); - -err_buf: - if (pd->uobject) - ib_umem_release(srq->umem); - else - mlx4_buf_free(dev->dev, buf_size, &srq->buf); - -err_db: - if (!pd->uobject) - mlx4_ib_db_free(dev, &srq->db); - -err_srq: - kfree(srq); - - return ERR_PTR(err); -} - -int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibsrq->device); - struct mlx4_ib_srq *srq = to_msrq(ibsrq); - int ret; - - /* We don't support resizing SRQs (yet?) */ - if (attr_mask & IB_SRQ_MAX_WR) - return -EINVAL; - - if (attr_mask & IB_SRQ_LIMIT) { - if (attr->srq_limit >= srq->msrq.max) - return -EINVAL; - - mutex_lock(&srq->mutex); - ret = mlx4_srq_arm(dev->dev, &srq->msrq, attr->srq_limit); - mutex_unlock(&srq->mutex); - - if (ret) - return ret; - } - - return 0; -} - -int mlx4_ib_destroy_srq(struct ib_srq *srq) -{ - struct mlx4_ib_dev *dev = to_mdev(srq->device); - struct mlx4_ib_srq *msrq = to_msrq(srq); - - mlx4_srq_free(dev->dev, &msrq->msrq); - mlx4_mtt_cleanup(dev->dev, &msrq->mtt); - - if (srq->uobject) { - mlx4_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db); - ib_umem_release(msrq->umem); - } else { - kfree(msrq->wrid); - mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift, - &msrq->buf); - mlx4_ib_db_free(dev, &msrq->db); - } - - kfree(msrq); - - return 0; -} - -void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index) -{ - struct mlx4_wqe_srq_next_seg *next; - - /* always called with interrupts disabled. */ - spin_lock(&srq->lock); - - next = get_wqe(srq, srq->tail); - next->next_wqe_index = cpu_to_be16(wqe_index); - srq->tail = wqe_index; - - spin_unlock(&srq->lock); -} - -int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct mlx4_ib_srq *srq = to_msrq(ibsrq); - struct mlx4_wqe_srq_next_seg *next; - struct mlx4_wqe_data_seg *scat; - unsigned long flags; - int err = 0; - int nreq; - int i; - - spin_lock_irqsave(&srq->lock, flags); - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (unlikely(wr->num_sge > srq->msrq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - break; - } - - srq->wrid[srq->head] = wr->wr_id; - - next = get_wqe(srq, srq->head); - srq->head = be16_to_cpu(next->next_wqe_index); - scat = (struct mlx4_wqe_data_seg *) (next + 1); - - for (i = 0; i < wr->num_sge; ++i) { - scat[i].byte_count = cpu_to_be32(wr->sg_list[i].length); - scat[i].lkey = cpu_to_be32(wr->sg_list[i].lkey); - scat[i].addr = cpu_to_be64(wr->sg_list[i].addr); - } - - if (i < srq->msrq.max_gs) { - scat[i].byte_count = 0; - scat[i].lkey = cpu_to_be32(MLX4_INVALID_LKEY); - scat[i].addr = 0; - } - } - - if (likely(nreq)) { - srq->wqe_ctr += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - *srq->db.db = cpu_to_be32(srq->wqe_ctr); - } - - spin_unlock_irqrestore(&srq->lock, flags); - - return err; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/user.h b/trunk/drivers/infiniband/hw/mlx4/user.h deleted file mode 100644 index 5b8eddc9fa83..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/user.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 MLX4_IB_USER_H -#define MLX4_IB_USER_H - -#include - -/* - * Increment this value if any changes that break userspace ABI - * compatibility are made. - */ -#define MLX4_IB_UVERBS_ABI_VERSION 1 - -/* - * 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 mlx4_ib_alloc_ucontext_resp { - __u32 qp_tab_size; - __u16 bf_reg_size; - __u16 bf_regs_per_page; -}; - -struct mlx4_ib_alloc_pd_resp { - __u32 pdn; - __u32 reserved; -}; - -struct mlx4_ib_create_cq { - __u64 buf_addr; - __u64 db_addr; -}; - -struct mlx4_ib_create_cq_resp { - __u32 cqn; - __u32 reserved; -}; - -struct mlx4_ib_resize_cq { - __u64 buf_addr; -}; - -struct mlx4_ib_create_srq { - __u64 buf_addr; - __u64 db_addr; -}; - -struct mlx4_ib_create_srq_resp { - __u32 srqn; - __u32 reserved; -}; - -struct mlx4_ib_create_qp { - __u64 buf_addr; - __u64 db_addr; -}; - -#endif /* MLX4_IB_USER_H */ diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c index 6bcde1cb9688..1c05486c3c68 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c @@ -37,7 +37,6 @@ */ #include -#include #include #include @@ -909,8 +908,6 @@ static struct ib_mr *mthca_get_dma_mr(struct ib_pd *pd, int acc) return ERR_PTR(err); } - mr->umem = NULL; - return &mr->ibmr; } @@ -1006,13 +1003,11 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, } kfree(page_list); - mr->umem = NULL; - return &mr->ibmr; } -static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int acc, struct ib_udata *udata) { struct mthca_dev *dev = to_mdev(pd->device); struct ib_umem_chunk *chunk; @@ -1023,26 +1018,20 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, int err = 0; int write_mtt_size; + shift = ffs(region->page_size) - 1; + mr = kmalloc(sizeof *mr, GFP_KERNEL); if (!mr) return ERR_PTR(-ENOMEM); - mr->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(mr->umem)) { - err = PTR_ERR(mr->umem); - goto err; - } - - shift = ffs(mr->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &mr->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; mr->mtt = mthca_alloc_mtt(dev, n); if (IS_ERR(mr->mtt)) { err = PTR_ERR(mr->mtt); - goto err_umem; + goto err; } pages = (u64 *) __get_free_page(GFP_KERNEL); @@ -1055,12 +1044,12 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages)); - list_for_each_entry(chunk, &mr->umem->chunk_list, list) + 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]) + - mr->umem->page_size * k; + region->page_size * k; /* * Be friendly to write_mtt and pass it chunks * of appropriate size. @@ -1082,8 +1071,8 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, if (err) goto err_mtt; - err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, virt, length, - convert_access(acc), mr); + err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, region->virt_base, + region->length, convert_access(acc), mr); if (err) goto err_mtt; @@ -1093,9 +1082,6 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, err_mtt: mthca_free_mtt(dev, mr->mtt); -err_umem: - ib_umem_release(mr->umem); - err: kfree(mr); return ERR_PTR(err); @@ -1104,12 +1090,8 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, static int mthca_dereg_mr(struct ib_mr *mr) { struct mthca_mr *mmr = to_mmr(mr); - mthca_free_mr(to_mdev(mr->device), mmr); - if (mmr->umem) - ib_umem_release(mmr->umem); kfree(mmr); - return 0; } diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h index 262616c8ebb6..1d266ac2e094 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h @@ -73,7 +73,6 @@ struct mthca_mtt; struct mthca_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct mthca_mtt *mtt; }; diff --git a/trunk/drivers/input/Kconfig b/trunk/drivers/input/Kconfig index f814fb3a469d..0e9b69535ad6 100644 --- a/trunk/drivers/input/Kconfig +++ b/trunk/drivers/input/Kconfig @@ -3,7 +3,6 @@ # menu "Input device support" - depends on !S390 config INPUT tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index b234729706be..55a72592704c 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -336,7 +336,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit, if (compat) { len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t); - if (len > maxlen) + if (len < maxlen) len = maxlen; for (i = 0; i < len / sizeof(compat_long_t); i++) diff --git a/trunk/drivers/input/misc/ixp4xx-beeper.c b/trunk/drivers/input/misc/ixp4xx-beeper.c index e759944041ab..3d4b619dadab 100644 --- a/trunk/drivers/input/misc/ixp4xx-beeper.c +++ b/trunk/drivers/input/misc/ixp4xx-beeper.c @@ -51,7 +51,7 @@ static void ixp4xx_spkr_control(unsigned int pin, unsigned int count) static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - unsigned int pin = (unsigned int) input_get_drvdata(dev); + unsigned int pin = (unsigned int) input_get_drvdata(input_dev); unsigned int count = 0; if (type != EV_SND) diff --git a/trunk/drivers/isdn/Kconfig b/trunk/drivers/isdn/Kconfig index d42fe89cddf6..c90afeea54aa 100644 --- a/trunk/drivers/isdn/Kconfig +++ b/trunk/drivers/isdn/Kconfig @@ -3,7 +3,6 @@ # menu "ISDN subsystem" - depends on !S390 config ISDN tristate "ISDN support" diff --git a/trunk/drivers/isdn/capi/Kconfig b/trunk/drivers/isdn/capi/Kconfig index c92f9d764fce..c921d6c522f5 100644 --- a/trunk/drivers/isdn/capi/Kconfig +++ b/trunk/drivers/isdn/capi/Kconfig @@ -17,7 +17,7 @@ config CAPI_TRACE help If you say Y here, the kernelcapi driver can make verbose traces of CAPI messages. This feature can be enabled/disabled via IOCTL for - every controller (default disabled). + every controler (default disabled). This will increase the size of the kernelcapi module by 20 KB. If unsure, say Y. diff --git a/trunk/drivers/isdn/gigaset/usb-gigaset.c b/trunk/drivers/isdn/gigaset/usb-gigaset.c index a1263019df5e..c8e1c357cec8 100644 --- a/trunk/drivers/isdn/gigaset/usb-gigaset.c +++ b/trunk/drivers/isdn/gigaset/usb-gigaset.c @@ -138,6 +138,8 @@ struct usb_cardstate { char bchars[6]; /* for request 0x19 */ }; +struct usb_bc_state {}; + static inline unsigned tiocm_to_gigaset(unsigned state) { return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0); @@ -577,21 +579,25 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) static int gigaset_freebcshw(struct bc_state *bcs) { - /* unused */ + if (!bcs->hw.usb) + return 0; + //FIXME + kfree(bcs->hw.usb); return 1; } /* Initialize the b-channel structure */ static int gigaset_initbcshw(struct bc_state *bcs) { - /* unused */ - bcs->hw.usb = NULL; + bcs->hw.usb = kmalloc(sizeof(struct usb_bc_state), GFP_KERNEL); + if (!bcs->hw.usb) + return 0; + return 1; } static void gigaset_reinitbcshw(struct bc_state *bcs) { - /* nothing to do for M10x */ } static void gigaset_freecshw(struct cardstate *cs) diff --git a/trunk/drivers/isdn/hardware/eicon/divasync.h b/trunk/drivers/isdn/hardware/eicon/divasync.h index 85784a7ffb25..af3eb9e795b5 100644 --- a/trunk/drivers/isdn/hardware/eicon/divasync.h +++ b/trunk/drivers/isdn/hardware/eicon/divasync.h @@ -216,7 +216,7 @@ typedef struct #define SERIAL_HOOK_RING 0x85 #define SERIAL_HOOK_DETACH 0x8f unsigned char Flags; /* function refinements */ - /* parameters passed by the ATTACH request */ + /* parameters passed by the the ATTACH request */ SERIAL_INT_CB InterruptHandler; /* called on each interrupt */ SERIAL_DPC_CB DeferredHandler; /* called on hook state changes */ void *HandlerContext; /* context for both handlers */ diff --git a/trunk/drivers/isdn/hisax/hfc_usb.c b/trunk/drivers/isdn/hisax/hfc_usb.c index 1f18f1993387..99e70d4103b6 100644 --- a/trunk/drivers/isdn/hisax/hfc_usb.c +++ b/trunk/drivers/isdn/hisax/hfc_usb.c @@ -1217,11 +1217,11 @@ usb_init(hfcusb_data * hfc) /* aux = output, reset off */ write_usb(hfc, HFCUSB_CIRM, 0x10); - /* set USB_SIZE to match the wMaxPacketSize for INT or BULK transfers */ + /* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */ write_usb(hfc, HFCUSB_USB_SIZE, (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4)); - /* set USB_SIZE_I to match the wMaxPacketSize for ISO transfers */ + /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */ write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size); /* enable PCM/GCI master mode */ diff --git a/trunk/drivers/kvm/Kconfig b/trunk/drivers/kvm/Kconfig index e8e37d826478..703cc88d1ef9 100644 --- a/trunk/drivers/kvm/Kconfig +++ b/trunk/drivers/kvm/Kconfig @@ -2,7 +2,6 @@ # KVM configuration # menu "Virtualization" - depends on X86 config KVM tristate "Kernel-based Virtual Machine (KVM) support" diff --git a/trunk/drivers/kvm/kvm_main.c b/trunk/drivers/kvm/kvm_main.c index 0d892600ff00..c8b8cfa332bb 100644 --- a/trunk/drivers/kvm/kvm_main.c +++ b/trunk/drivers/kvm/kvm_main.c @@ -2889,9 +2889,7 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, switch (val) { case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", cpu); decache_vcpus_on_cpu(cpu); @@ -2899,7 +2897,6 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, NULL, 0, 1); break; case CPU_ONLINE: - case CPU_ONLINE_FROZEN: printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", cpu); smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 87d2046f866c..80acd08f0e97 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -1,6 +1,5 @@ menu "LED devices" - depends on HAS_IOMEM config NEW_LEDS bool "LED Support" diff --git a/trunk/drivers/leds/leds-h1940.c b/trunk/drivers/leds/leds-h1940.c index 677c99325be5..1d49d2ade557 100644 --- a/trunk/drivers/leds/leds-h1940.c +++ b/trunk/drivers/leds/leds-h1940.c @@ -1,5 +1,5 @@ /* - * drivers/leds/leds-h1940.c + * drivers/leds/h1940-leds.c * Copyright (c) Arnaud Patard * * This file is subject to the terms and conditions of the GNU General Public diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig index 58926da0ae18..a32c91e27b3c 100644 --- a/trunk/drivers/macintosh/Kconfig +++ b/trunk/drivers/macintosh/Kconfig @@ -237,7 +237,7 @@ config PMAC_RACKMETER tristate "Support for Apple XServe front panel LEDs" depends on PPC_PMAC help - This driver provides some support to control the front panel + This driver procides some support to control the front panel blue LEDs "vu-meter" of the XServer macs. endif # MACINTOSH_DRIVERS diff --git a/trunk/drivers/macintosh/mediabay.c b/trunk/drivers/macintosh/mediabay.c index c803d2bba65d..0acf2f7fd9d7 100644 --- a/trunk/drivers/macintosh/mediabay.c +++ b/trunk/drivers/macintosh/mediabay.c @@ -563,7 +563,7 @@ static void media_bay_step(int i) ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); hw.irq = bay->cd_irq; hw.chipset = ide_pmac; - bay->cd_index = ide_register_hw(&hw, 0, NULL); + bay->cd_index = ide_register_hw(&hw, NULL); pmu_resume(); } if (bay->cd_index == -1) { diff --git a/trunk/drivers/mca/mca-bus.c b/trunk/drivers/mca/mca-bus.c index 67b8e9453b19..da862e4632dd 100644 --- a/trunk/drivers/mca/mca-bus.c +++ b/trunk/drivers/mca/mca-bus.c @@ -47,25 +47,19 @@ static int mca_bus_match (struct device *dev, struct device_driver *drv) { struct mca_device *mca_dev = to_mca_device (dev); struct mca_driver *mca_drv = to_mca_driver (drv); - const unsigned short *mca_ids = mca_drv->id_table; - int i = 0; - - if (mca_ids) { - for(i = 0; mca_ids[i]; i++) { - if (mca_ids[i] == mca_dev->pos_id) { - mca_dev->index = i; - return 1; - } + const short *mca_ids = mca_drv->id_table; + int i; + + if (!mca_ids) + return 0; + + for(i = 0; mca_ids[i]; i++) { + if (mca_ids[i] == mca_dev->pos_id) { + mca_dev->index = i; + return 1; } } - /* If the integrated id is present, treat it as though it were an - * additional id in the id_table (it can't be because by definition, - * integrated id's overflow a short */ - if (mca_drv->integrated_id && mca_dev->pos_id == - mca_drv->integrated_id) { - mca_dev->index = i; - return 1; - } + return 0; } diff --git a/trunk/drivers/mca/mca-driver.c b/trunk/drivers/mca/mca-driver.c index 32cd39bcc715..2223466b3d8a 100644 --- a/trunk/drivers/mca/mca-driver.c +++ b/trunk/drivers/mca/mca-driver.c @@ -36,25 +36,12 @@ int mca_register_driver(struct mca_driver *mca_drv) mca_drv->driver.bus = &mca_bus_type; if ((r = driver_register(&mca_drv->driver)) < 0) return r; - mca_drv->integrated_id = 0; } return 0; } EXPORT_SYMBOL(mca_register_driver); -int mca_register_driver_integrated(struct mca_driver *mca_driver, - int integrated_id) -{ - int r = mca_register_driver(mca_driver); - - if (!r) - mca_driver->integrated_id = integrated_id; - - return r; -} -EXPORT_SYMBOL(mca_register_driver_integrated); - void mca_unregister_driver(struct mca_driver *mca_drv) { if (MCA_bus) diff --git a/trunk/drivers/md/Kconfig b/trunk/drivers/md/Kconfig index 7df934d69134..4540ade6b6b5 100644 --- a/trunk/drivers/md/Kconfig +++ b/trunk/drivers/md/Kconfig @@ -262,15 +262,6 @@ config DM_MULTIPATH_EMC ---help--- Multipath support for EMC CX/AX series hardware. -config DM_DELAY - tristate "I/O delaying target (EXPERIMENTAL)" - depends on BLK_DEV_DM && EXPERIMENTAL - ---help--- - A target that delays reads and/or writes and can send - them to different devices. Useful for testing. - - If unsure, say N. - endmenu endif diff --git a/trunk/drivers/md/Makefile b/trunk/drivers/md/Makefile index 38754084eac7..34957a68d921 100644 --- a/trunk/drivers/md/Makefile +++ b/trunk/drivers/md/Makefile @@ -31,7 +31,6 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o obj-$(CONFIG_BLK_DEV_MD) += md-mod.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o -obj-$(CONFIG_DM_DELAY) += dm-delay.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o diff --git a/trunk/drivers/md/dm-bio-list.h b/trunk/drivers/md/dm-bio-list.h index c6be88826fae..da4349649f7f 100644 --- a/trunk/drivers/md/dm-bio-list.h +++ b/trunk/drivers/md/dm-bio-list.h @@ -8,43 +8,17 @@ #define DM_BIO_LIST_H #include -#include struct bio_list { struct bio *head; struct bio *tail; }; -static inline int bio_list_empty(const struct bio_list *bl) -{ - return bl->head == NULL; -} - -#define BIO_LIST_INIT { .head = NULL, .tail = NULL } - -#define BIO_LIST(bl) \ - struct bio_list bl = BIO_LIST_INIT - static inline void bio_list_init(struct bio_list *bl) { bl->head = bl->tail = NULL; } -#define bio_list_for_each(bio, bl) \ - for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \ - bio = bio->bi_next) - -static inline unsigned bio_list_size(const struct bio_list *bl) -{ - unsigned sz = 0; - struct bio *bio; - - bio_list_for_each(bio, bl) - sz++; - - return sz; -} - static inline void bio_list_add(struct bio_list *bl, struct bio *bio) { bio->bi_next = NULL; diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index 7b0fcfc9eaa5..d8121234c347 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -33,6 +33,7 @@ struct crypt_io { struct dm_target *target; struct bio *base_bio; + struct bio *first_clone; struct work_struct work; atomic_t pending; int error; @@ -106,8 +107,6 @@ struct crypt_config { static struct kmem_cache *_crypt_io_pool; -static void clone_init(struct crypt_io *, struct bio *); - /* * Different IV generation algorithms: * @@ -121,9 +120,6 @@ static void clone_init(struct crypt_io *, struct bio *); * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1 * (needed for LRW-32-AES and possible other narrow block modes) * - * null: the initial vector is always zero. Provides compatibility with - * obsolete loop_fish2 devices. Do not use for new devices. - * * plumb: unimplemented, see: * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 */ @@ -260,13 +256,6 @@ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) return 0; } -static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector) -{ - memset(iv, 0, cc->iv_size); - - return 0; -} - static struct crypt_iv_operations crypt_iv_plain_ops = { .generator = crypt_iv_plain_gen }; @@ -283,10 +272,6 @@ static struct crypt_iv_operations crypt_iv_benbi_ops = { .generator = crypt_iv_benbi_gen }; -static struct crypt_iv_operations crypt_iv_null_ops = { - .generator = crypt_iv_null_gen -}; - static int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, @@ -393,21 +378,36 @@ static int crypt_convert(struct crypt_config *cc, * This should never violate the device limitations * May return a smaller bio when running out of pages */ -static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) +static struct bio * +crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, + struct bio *base_bio, unsigned int *bio_vec_idx) { - struct crypt_config *cc = io->target->private; struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; unsigned int i; - clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); + if (base_bio) { + clone = bio_alloc_bioset(GFP_NOIO, base_bio->bi_max_vecs, cc->bs); + __bio_clone(clone, base_bio); + } else + clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); + if (!clone) return NULL; - clone_init(io, clone); + clone->bi_destructor = dm_crypt_bio_destructor; - for (i = 0; i < nr_iovecs; i++) { + /* if the last bio was not complete, continue where that one ended */ + clone->bi_idx = *bio_vec_idx; + clone->bi_vcnt = *bio_vec_idx; + clone->bi_size = 0; + clone->bi_flags &= ~(1 << BIO_SEG_VALID); + + /* clone->bi_idx pages have already been allocated */ + size -= clone->bi_idx * PAGE_SIZE; + + for (i = clone->bi_idx; i < nr_iovecs; i++) { struct bio_vec *bv = bio_iovec_idx(clone, i); bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask); @@ -419,7 +419,7 @@ static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) * return a partially allocated bio, the caller will then try * to allocate additional bios while submitting this partial bio */ - if (i == (MIN_BIO_PAGES - 1)) + if ((i - clone->bi_idx) == (MIN_BIO_PAGES - 1)) gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; bv->bv_offset = 0; @@ -438,6 +438,12 @@ static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) return NULL; } + /* + * Remember the last bio_vec allocated to be able + * to correctly continue after the splitting. + */ + *bio_vec_idx = clone->bi_vcnt; + return clone; } @@ -489,6 +495,9 @@ static void dec_pending(struct crypt_io *io, int error) if (!atomic_dec_and_test(&io->pending)) return; + if (io->first_clone) + bio_put(io->first_clone); + bio_endio(io->base_bio, io->base_bio->bi_size, io->error); mempool_free(io, cc->io_pool); @@ -553,7 +562,6 @@ static void clone_init(struct crypt_io *io, struct bio *clone) clone->bi_end_io = crypt_endio; clone->bi_bdev = cc->dev->bdev; clone->bi_rw = io->base_bio->bi_rw; - clone->bi_destructor = dm_crypt_bio_destructor; } static void process_read(struct crypt_io *io) @@ -577,6 +585,7 @@ static void process_read(struct crypt_io *io) } clone_init(io, clone); + clone->bi_destructor = dm_crypt_bio_destructor; clone->bi_idx = 0; clone->bi_vcnt = bio_segments(base_bio); clone->bi_size = base_bio->bi_size; @@ -595,6 +604,7 @@ static void process_write(struct crypt_io *io) struct convert_context ctx; unsigned remaining = base_bio->bi_size; sector_t sector = base_bio->bi_sector - io->target->begin; + unsigned bvec_idx = 0; atomic_inc(&io->pending); @@ -605,14 +615,14 @@ static void process_write(struct crypt_io *io) * so repeat the whole process until all the data can be handled. */ while (remaining) { - clone = crypt_alloc_buffer(io, remaining); + clone = crypt_alloc_buffer(cc, base_bio->bi_size, + io->first_clone, &bvec_idx); if (unlikely(!clone)) { dec_pending(io, -ENOMEM); return; } ctx.bio_out = clone; - ctx.idx_out = 0; if (unlikely(crypt_convert(cc, &ctx) < 0)) { crypt_free_buffer_pages(cc, clone, clone->bi_size); @@ -621,26 +631,31 @@ static void process_write(struct crypt_io *io) return; } - /* crypt_convert should have filled the clone bio */ - BUG_ON(ctx.idx_out < clone->bi_vcnt); - + clone_init(io, clone); clone->bi_sector = cc->start + sector; + + if (!io->first_clone) { + /* + * hold a reference to the first clone, because it + * holds the bio_vec array and that can't be freed + * before all other clones are released + */ + bio_get(clone); + io->first_clone = clone; + } + remaining -= clone->bi_size; sector += bio_sectors(clone); - /* Grab another reference to the io struct - * before we kick off the request */ + /* prevent bio_put of first_clone */ if (remaining) atomic_inc(&io->pending); generic_make_request(clone); - /* Do not reference clone after this - it - * may be gone already. */ - /* out of memory -> run queues */ if (remaining) - congestion_wait(WRITE, HZ/100); + congestion_wait(bio_data_dir(clone), HZ/100); } } @@ -817,8 +832,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops = &crypt_iv_essiv_ops; else if (strcmp(ivmode, "benbi") == 0) cc->iv_gen_ops = &crypt_iv_benbi_ops; - else if (strcmp(ivmode, "null") == 0) - cc->iv_gen_ops = &crypt_iv_null_ops; else { ti->error = "Invalid IV mode"; goto bad2; @@ -941,12 +954,10 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, struct crypt_config *cc = ti->private; struct crypt_io *io; - if (bio_barrier(bio)) - return -EOPNOTSUPP; - io = mempool_alloc(cc->io_pool, GFP_NOIO); io->target = ti; io->base_bio = bio; + io->first_clone = NULL; io->error = io->post_process = 0; atomic_set(&io->pending, 0); kcryptd_queue_io(io); @@ -1046,7 +1057,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) static struct target_type crypt_target = { .name = "crypt", - .version= {1, 5, 0}, + .version= {1, 3, 0}, .module = THIS_MODULE, .ctr = crypt_ctr, .dtr = crypt_dtr, diff --git a/trunk/drivers/md/dm-delay.c b/trunk/drivers/md/dm-delay.c deleted file mode 100644 index 52c7cf9e5803..000000000000 --- a/trunk/drivers/md/dm-delay.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2005-2007 Red Hat GmbH - * - * A target that delays reads and/or writes and can send - * them to different devices. - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include - -#include "dm.h" -#include "dm-bio-list.h" - -#define DM_MSG_PREFIX "delay" - -struct delay_c { - struct timer_list delay_timer; - struct semaphore timer_lock; - struct work_struct flush_expired_bios; - struct list_head delayed_bios; - atomic_t may_delay; - mempool_t *delayed_pool; - - struct dm_dev *dev_read; - sector_t start_read; - unsigned read_delay; - unsigned reads; - - struct dm_dev *dev_write; - sector_t start_write; - unsigned write_delay; - unsigned writes; -}; - -struct delay_info { - struct delay_c *context; - struct list_head list; - struct bio *bio; - unsigned long expires; -}; - -static DEFINE_MUTEX(delayed_bios_lock); - -static struct workqueue_struct *kdelayd_wq; -static struct kmem_cache *delayed_cache; - -static void handle_delayed_timer(unsigned long data) -{ - struct delay_c *dc = (struct delay_c *)data; - - queue_work(kdelayd_wq, &dc->flush_expired_bios); -} - -static void queue_timeout(struct delay_c *dc, unsigned long expires) -{ - down(&dc->timer_lock); - - if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires) - mod_timer(&dc->delay_timer, expires); - - up(&dc->timer_lock); -} - -static void flush_bios(struct bio *bio) -{ - struct bio *n; - - while (bio) { - n = bio->bi_next; - bio->bi_next = NULL; - generic_make_request(bio); - bio = n; - } -} - -static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) -{ - struct delay_info *delayed, *next; - unsigned long next_expires = 0; - int start_timer = 0; - BIO_LIST(flush_bios); - - mutex_lock(&delayed_bios_lock); - list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { - if (flush_all || time_after_eq(jiffies, delayed->expires)) { - list_del(&delayed->list); - bio_list_add(&flush_bios, delayed->bio); - if ((bio_data_dir(delayed->bio) == WRITE)) - delayed->context->writes--; - else - delayed->context->reads--; - mempool_free(delayed, dc->delayed_pool); - continue; - } - - if (!start_timer) { - start_timer = 1; - next_expires = delayed->expires; - } else - next_expires = min(next_expires, delayed->expires); - } - - mutex_unlock(&delayed_bios_lock); - - if (start_timer) - queue_timeout(dc, next_expires); - - return bio_list_get(&flush_bios); -} - -static void flush_expired_bios(struct work_struct *work) -{ - struct delay_c *dc; - - dc = container_of(work, struct delay_c, flush_expired_bios); - flush_bios(flush_delayed_bios(dc, 0)); -} - -/* - * Mapping parameters: - * [ ] - * - * With separate write parameters, the first set is only used for reads. - * Delays are specified in milliseconds. - */ -static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) -{ - struct delay_c *dc; - unsigned long long tmpll; - - if (argc != 3 && argc != 6) { - ti->error = "requires exactly 3 or 6 arguments"; - return -EINVAL; - } - - dc = kmalloc(sizeof(*dc), GFP_KERNEL); - if (!dc) { - ti->error = "Cannot allocate context"; - return -ENOMEM; - } - - dc->reads = dc->writes = 0; - - if (sscanf(argv[1], "%llu", &tmpll) != 1) { - ti->error = "Invalid device sector"; - goto bad; - } - dc->start_read = tmpll; - - if (sscanf(argv[2], "%u", &dc->read_delay) != 1) { - ti->error = "Invalid delay"; - goto bad; - } - - if (dm_get_device(ti, argv[0], dc->start_read, ti->len, - dm_table_get_mode(ti->table), &dc->dev_read)) { - ti->error = "Device lookup failed"; - goto bad; - } - - if (argc == 3) { - dc->dev_write = NULL; - goto out; - } - - if (sscanf(argv[4], "%llu", &tmpll) != 1) { - ti->error = "Invalid write device sector"; - goto bad; - } - dc->start_write = tmpll; - - if (sscanf(argv[5], "%u", &dc->write_delay) != 1) { - ti->error = "Invalid write delay"; - goto bad; - } - - if (dm_get_device(ti, argv[3], dc->start_write, ti->len, - dm_table_get_mode(ti->table), &dc->dev_write)) { - ti->error = "Write device lookup failed"; - dm_put_device(ti, dc->dev_read); - goto bad; - } - -out: - dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache); - if (!dc->delayed_pool) { - DMERR("Couldn't create delayed bio pool."); - goto bad; - } - - init_timer(&dc->delay_timer); - dc->delay_timer.function = handle_delayed_timer; - dc->delay_timer.data = (unsigned long)dc; - - INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); - INIT_LIST_HEAD(&dc->delayed_bios); - init_MUTEX(&dc->timer_lock); - atomic_set(&dc->may_delay, 1); - - ti->private = dc; - return 0; - -bad: - kfree(dc); - return -EINVAL; -} - -static void delay_dtr(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - flush_workqueue(kdelayd_wq); - - dm_put_device(ti, dc->dev_read); - - if (dc->dev_write) - dm_put_device(ti, dc->dev_write); - - mempool_destroy(dc->delayed_pool); - kfree(dc); -} - -static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) -{ - struct delay_info *delayed; - unsigned long expires = 0; - - if (!delay || !atomic_read(&dc->may_delay)) - return 1; - - delayed = mempool_alloc(dc->delayed_pool, GFP_NOIO); - - delayed->context = dc; - delayed->bio = bio; - delayed->expires = expires = jiffies + (delay * HZ / 1000); - - mutex_lock(&delayed_bios_lock); - - if (bio_data_dir(bio) == WRITE) - dc->writes++; - else - dc->reads++; - - list_add_tail(&delayed->list, &dc->delayed_bios); - - mutex_unlock(&delayed_bios_lock); - - queue_timeout(dc, expires); - - return 0; -} - -static void delay_presuspend(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 0); - del_timer_sync(&dc->delay_timer); - flush_bios(flush_delayed_bios(dc, 1)); -} - -static void delay_resume(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 1); -} - -static int delay_map(struct dm_target *ti, struct bio *bio, - union map_info *map_context) -{ - struct delay_c *dc = ti->private; - - if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { - bio->bi_bdev = dc->dev_write->bdev; - bio->bi_sector = dc->start_write + - (bio->bi_sector - ti->begin); - - return delay_bio(dc, dc->write_delay, bio); - } - - bio->bi_bdev = dc->dev_read->bdev; - bio->bi_sector = dc->start_read + - (bio->bi_sector - ti->begin); - - return delay_bio(dc, dc->read_delay, bio); -} - -static int delay_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) -{ - struct delay_c *dc = ti->private; - int sz = 0; - - switch (type) { - case STATUSTYPE_INFO: - DMEMIT("%u %u", dc->reads, dc->writes); - break; - - case STATUSTYPE_TABLE: - DMEMIT("%s %llu %u", dc->dev_read->name, - (unsigned long long) dc->start_read, - dc->read_delay); - if (dc->dev_write) - DMEMIT("%s %llu %u", dc->dev_write->name, - (unsigned long long) dc->start_write, - dc->write_delay); - break; - } - - return 0; -} - -static struct target_type delay_target = { - .name = "delay", - .version = {1, 0, 2}, - .module = THIS_MODULE, - .ctr = delay_ctr, - .dtr = delay_dtr, - .map = delay_map, - .presuspend = delay_presuspend, - .resume = delay_resume, - .status = delay_status, -}; - -static int __init dm_delay_init(void) -{ - int r = -ENOMEM; - - kdelayd_wq = create_workqueue("kdelayd"); - if (!kdelayd_wq) { - DMERR("Couldn't start kdelayd"); - goto bad_queue; - } - - delayed_cache = kmem_cache_create("dm-delay", - sizeof(struct delay_info), - __alignof__(struct delay_info), - 0, NULL, NULL); - if (!delayed_cache) { - DMERR("Couldn't create delayed bio cache."); - goto bad_memcache; - } - - r = dm_register_target(&delay_target); - if (r < 0) { - DMERR("register failed %d", r); - goto bad_register; - } - - return 0; - -bad_register: - kmem_cache_destroy(delayed_cache); -bad_memcache: - destroy_workqueue(kdelayd_wq); -bad_queue: - return r; -} - -static void __exit dm_delay_exit(void) -{ - int r = dm_unregister_target(&delay_target); - - if (r < 0) - DMERR("unregister failed %d", r); - - kmem_cache_destroy(delayed_cache); - destroy_workqueue(kdelayd_wq); -} - -/* Module hooks */ -module_init(dm_delay_init); -module_exit(dm_delay_exit); - -MODULE_DESCRIPTION(DM_NAME " delay target"); -MODULE_AUTHOR("Heinz Mauelshagen "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/md/dm-exception-store.c b/trunk/drivers/md/dm-exception-store.c index 07e0a0c84f6e..99cdffa7fbfe 100644 --- a/trunk/drivers/md/dm-exception-store.c +++ b/trunk/drivers/md/dm-exception-store.c @@ -1,8 +1,7 @@ /* - * dm-exception-store.c + * dm-snapshot.c * * Copyright (C) 2001-2002 Sistina Software (UK) Limited. - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. */ @@ -124,7 +123,6 @@ struct pstore { atomic_t pending_count; uint32_t callback_count; struct commit_callback *callbacks; - struct dm_io_client *io_client; }; static inline unsigned int sectors_to_pages(unsigned int sectors) @@ -161,20 +159,14 @@ static void free_area(struct pstore *ps) */ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw) { - struct io_region where = { - .bdev = ps->snap->cow->bdev, - .sector = ps->snap->chunk_size * chunk, - .count = ps->snap->chunk_size, - }; - struct dm_io_request io_req = { - .bi_rw = rw, - .mem.type = DM_IO_VMA, - .mem.ptr.vma = ps->area, - .client = ps->io_client, - .notify.fn = NULL, - }; - - return dm_io(&io_req, 1, &where, NULL); + struct io_region where; + unsigned long bits; + + where.bdev = ps->snap->cow->bdev; + where.sector = ps->snap->chunk_size * chunk; + where.count = ps->snap->chunk_size; + + return dm_io_sync_vm(1, &where, rw, ps->area, &bits); } /* @@ -221,18 +213,17 @@ static int read_header(struct pstore *ps, int *new_snapshot) chunk_size_supplied = 0; } - ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap-> - chunk_size)); - if (IS_ERR(ps->io_client)) - return PTR_ERR(ps->io_client); + r = dm_io_get(sectors_to_pages(ps->snap->chunk_size)); + if (r) + return r; r = alloc_area(ps); if (r) - return r; + goto bad1; r = chunk_io(ps, 0, READ); if (r) - goto bad; + goto bad2; dh = (struct disk_header *) ps->area; @@ -244,7 +235,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) if (le32_to_cpu(dh->magic) != SNAP_MAGIC) { DMWARN("Invalid or corrupt snapshot"); r = -ENXIO; - goto bad; + goto bad2; } *new_snapshot = 0; @@ -261,22 +252,27 @@ static int read_header(struct pstore *ps, int *new_snapshot) (unsigned long long)ps->snap->chunk_size); /* We had a bogus chunk_size. Fix stuff up. */ + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); free_area(ps); ps->snap->chunk_size = chunk_size; ps->snap->chunk_mask = chunk_size - 1; ps->snap->chunk_shift = ffs(chunk_size) - 1; - r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size), - ps->io_client); + r = dm_io_get(sectors_to_pages(chunk_size)); if (r) return r; r = alloc_area(ps); - return r; + if (r) + goto bad1; + + return 0; -bad: +bad2: free_area(ps); +bad1: + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); return r; } @@ -409,7 +405,7 @@ static void persistent_destroy(struct exception_store *store) { struct pstore *ps = get_info(store); - dm_io_client_destroy(ps->io_client); + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); vfree(ps->callbacks); free_area(ps); kfree(ps); diff --git a/trunk/drivers/md/dm-hw-handler.h b/trunk/drivers/md/dm-hw-handler.h index e0832e6fcf36..32eff28e4adc 100644 --- a/trunk/drivers/md/dm-hw-handler.h +++ b/trunk/drivers/md/dm-hw-handler.h @@ -16,7 +16,6 @@ struct hw_handler_type; struct hw_handler { struct hw_handler_type *type; - struct mapped_device *md; void *context; }; diff --git a/trunk/drivers/md/dm-io.c b/trunk/drivers/md/dm-io.c index 352c6fbeac53..8bdc8a87b249 100644 --- a/trunk/drivers/md/dm-io.c +++ b/trunk/drivers/md/dm-io.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2003 Sistina Software - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. */ @@ -13,17 +12,13 @@ #include #include -struct dm_io_client { - mempool_t *pool; - struct bio_set *bios; -}; +static struct bio_set *_bios; /* FIXME: can we shrink this ? */ struct io { unsigned long error; atomic_t count; struct task_struct *sleeper; - struct dm_io_client *client; io_notify_fn callback; void *context; }; @@ -31,58 +26,63 @@ struct io { /* * io contexts are only dynamically allocated for asynchronous * io. Since async io is likely to be the majority of io we'll - * have the same number of io contexts as bios! (FIXME: must reduce this). + * have the same number of io contexts as buffer heads ! (FIXME: + * must reduce this). */ +static unsigned _num_ios; +static mempool_t *_io_pool; static unsigned int pages_to_ios(unsigned int pages) { return 4 * pages; /* too many ? */ } -/* - * Create a client with mempool and bioset. - */ -struct dm_io_client *dm_io_client_create(unsigned num_pages) +static int resize_pool(unsigned int new_ios) { - unsigned ios = pages_to_ios(num_pages); - struct dm_io_client *client; - - client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return ERR_PTR(-ENOMEM); - - client->pool = mempool_create_kmalloc_pool(ios, sizeof(struct io)); - if (!client->pool) - goto bad; + int r = 0; + + if (_io_pool) { + if (new_ios == 0) { + /* free off the pool */ + mempool_destroy(_io_pool); + _io_pool = NULL; + bioset_free(_bios); + + } else { + /* resize the pool */ + r = mempool_resize(_io_pool, new_ios, GFP_KERNEL); + } - client->bios = bioset_create(16, 16); - if (!client->bios) - goto bad; + } else { + /* create new pool */ + _io_pool = mempool_create_kmalloc_pool(new_ios, + sizeof(struct io)); + if (!_io_pool) + return -ENOMEM; + + _bios = bioset_create(16, 16); + if (!_bios) { + mempool_destroy(_io_pool); + _io_pool = NULL; + return -ENOMEM; + } + } - return client; + if (!r) + _num_ios = new_ios; - bad: - if (client->pool) - mempool_destroy(client->pool); - kfree(client); - return ERR_PTR(-ENOMEM); + return r; } -EXPORT_SYMBOL(dm_io_client_create); -int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client) +int dm_io_get(unsigned int num_pages) { - return mempool_resize(client->pool, pages_to_ios(num_pages), - GFP_KERNEL); + return resize_pool(_num_ios + pages_to_ios(num_pages)); } -EXPORT_SYMBOL(dm_io_client_resize); -void dm_io_client_destroy(struct dm_io_client *client) +void dm_io_put(unsigned int num_pages) { - mempool_destroy(client->pool); - bioset_free(client->bios); - kfree(client); + resize_pool(_num_ios - pages_to_ios(num_pages)); } -EXPORT_SYMBOL(dm_io_client_destroy); /*----------------------------------------------------------------- * We need to keep track of which region a bio is doing io for. @@ -118,7 +118,7 @@ static void dec_count(struct io *io, unsigned int region, int error) io_notify_fn fn = io->callback; void *context = io->context; - mempool_free(io, io->client->pool); + mempool_free(io, _io_pool); fn(r, context); } } @@ -126,8 +126,7 @@ static void dec_count(struct io *io, unsigned int region, int error) static int endio(struct bio *bio, unsigned int done, int error) { - struct io *io; - unsigned region; + struct io *io = (struct io *) bio->bi_private; /* keep going until we've finished */ if (bio->bi_size) @@ -136,17 +135,10 @@ static int endio(struct bio *bio, unsigned int done, int error) if (error && bio_data_dir(bio) == READ) zero_fill_bio(bio); - /* - * The bio destructor in bio_put() may use the io object. - */ - io = bio->bi_private; - region = bio_get_region(bio); - + dec_count(io, bio_get_region(bio), error); bio->bi_max_vecs++; bio_put(bio); - dec_count(io, region, error); - return 0; } @@ -217,9 +209,6 @@ static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec) dp->context_ptr = bvec; } -/* - * Functions for getting the pages from a VMA. - */ static void vm_get_page(struct dpages *dp, struct page **p, unsigned long *len, unsigned *offset) { @@ -244,34 +233,7 @@ static void vm_dp_init(struct dpages *dp, void *data) static void dm_bio_destructor(struct bio *bio) { - struct io *io = bio->bi_private; - - bio_free(bio, io->client->bios); -} - -/* - * Functions for getting the pages from kernel memory. - */ -static void km_get_page(struct dpages *dp, struct page **p, unsigned long *len, - unsigned *offset) -{ - *p = virt_to_page(dp->context_ptr); - *offset = dp->context_u; - *len = PAGE_SIZE - dp->context_u; -} - -static void km_next_page(struct dpages *dp) -{ - dp->context_ptr += PAGE_SIZE - dp->context_u; - dp->context_u = 0; -} - -static void km_dp_init(struct dpages *dp, void *data) -{ - dp->get_page = km_get_page; - dp->next_page = km_next_page; - dp->context_u = ((unsigned long) data) & (PAGE_SIZE - 1); - dp->context_ptr = data; + bio_free(bio, _bios); } /*----------------------------------------------------------------- @@ -294,7 +256,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, * to hide it from bio_add_page(). */ num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; - bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); + bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; @@ -349,9 +311,8 @@ static void dispatch_io(int rw, unsigned int num_regions, dec_count(io, 0, 0); } -static int sync_io(struct dm_io_client *client, unsigned int num_regions, - struct io_region *where, int rw, struct dpages *dp, - unsigned long *error_bits) +static int sync_io(unsigned int num_regions, struct io_region *where, + int rw, struct dpages *dp, unsigned long *error_bits) { struct io io; @@ -363,7 +324,6 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, io.error = 0; atomic_set(&io.count, 1); /* see dispatch_io() */ io.sleeper = current; - io.client = client; dispatch_io(rw, num_regions, where, dp, &io, 1); @@ -380,15 +340,12 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, if (atomic_read(&io.count)) return -EINTR; - if (error_bits) - *error_bits = io.error; - + *error_bits = io.error; return io.error ? -EIO : 0; } -static int async_io(struct dm_io_client *client, unsigned int num_regions, - struct io_region *where, int rw, struct dpages *dp, - io_notify_fn fn, void *context) +static int async_io(unsigned int num_regions, struct io_region *where, int rw, + struct dpages *dp, io_notify_fn fn, void *context) { struct io *io; @@ -398,11 +355,10 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, return -EIO; } - io = mempool_alloc(client->pool, GFP_NOIO); + io = mempool_alloc(_io_pool, GFP_NOIO); io->error = 0; atomic_set(&io->count, 1); /* see dispatch_io() */ io->sleeper = NULL; - io->client = client; io->callback = fn; io->context = context; @@ -410,51 +366,61 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, return 0; } -static int dp_init(struct dm_io_request *io_req, struct dpages *dp) +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits) { - /* Set up dpages based on memory type */ - switch (io_req->mem.type) { - case DM_IO_PAGE_LIST: - list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset); - break; - - case DM_IO_BVEC: - bvec_dp_init(dp, io_req->mem.ptr.bvec); - break; - - case DM_IO_VMA: - vm_dp_init(dp, io_req->mem.ptr.vma); - break; - - case DM_IO_KMEM: - km_dp_init(dp, io_req->mem.ptr.addr); - break; - - default: - return -EINVAL; - } + struct dpages dp; + list_dp_init(&dp, pl, offset); + return sync_io(num_regions, where, rw, &dp, error_bits); +} - return 0; +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return sync_io(num_regions, where, rw, &dp, error_bits); } -/* - * New collapsed (a)synchronous interface - */ -int dm_io(struct dm_io_request *io_req, unsigned num_regions, - struct io_region *where, unsigned long *sync_error_bits) +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits) { - int r; struct dpages dp; + vm_dp_init(&dp, data); + return sync_io(num_regions, where, rw, &dp, error_bits); +} - r = dp_init(io_req, &dp); - if (r) - return r; +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context) +{ + struct dpages dp; + list_dp_init(&dp, pl, offset); + return async_io(num_regions, where, rw, &dp, fn, context); +} - if (!io_req->notify.fn) - return sync_io(io_req->client, num_regions, where, - io_req->bi_rw, &dp, sync_error_bits); +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return async_io(num_regions, where, rw, &dp, fn, context); +} - return async_io(io_req->client, num_regions, where, io_req->bi_rw, - &dp, io_req->notify.fn, io_req->notify.context); +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context) +{ + struct dpages dp; + vm_dp_init(&dp, data); + return async_io(num_regions, where, rw, &dp, fn, context); } -EXPORT_SYMBOL(dm_io); + +EXPORT_SYMBOL(dm_io_get); +EXPORT_SYMBOL(dm_io_put); +EXPORT_SYMBOL(dm_io_sync); +EXPORT_SYMBOL(dm_io_async); +EXPORT_SYMBOL(dm_io_sync_bvec); +EXPORT_SYMBOL(dm_io_async_bvec); +EXPORT_SYMBOL(dm_io_sync_vm); +EXPORT_SYMBOL(dm_io_async_vm); diff --git a/trunk/drivers/md/dm-io.h b/trunk/drivers/md/dm-io.h index f647e2cceaa6..f9035bfd1a9f 100644 --- a/trunk/drivers/md/dm-io.h +++ b/trunk/drivers/md/dm-io.h @@ -12,7 +12,7 @@ struct io_region { struct block_device *bdev; sector_t sector; - sector_t count; /* If this is zero the region is ignored. */ + sector_t count; }; struct page_list { @@ -20,60 +20,55 @@ struct page_list { struct page *page; }; -typedef void (*io_notify_fn)(unsigned long error, void *context); - -enum dm_io_mem_type { - DM_IO_PAGE_LIST,/* Page list */ - DM_IO_BVEC, /* Bio vector */ - DM_IO_VMA, /* Virtual memory area */ - DM_IO_KMEM, /* Kernel memory */ -}; -struct dm_io_memory { - enum dm_io_mem_type type; - - union { - struct page_list *pl; - struct bio_vec *bvec; - void *vma; - void *addr; - } ptr; +/* + * 'error' is a bitset, with each bit indicating whether an error + * occurred doing io to the corresponding region. + */ +typedef void (*io_notify_fn)(unsigned long error, void *context); - unsigned offset; -}; - -struct dm_io_notify { - io_notify_fn fn; /* Callback for asynchronous requests */ - void *context; /* Passed to callback */ -}; /* - * IO request structure + * Before anyone uses the IO interface they should call + * dm_io_get(), specifying roughly how many pages they are + * expecting to perform io on concurrently. + * + * This function may block. */ -struct dm_io_client; -struct dm_io_request { - int bi_rw; /* READ|WRITE - not READA */ - struct dm_io_memory mem; /* Memory to use for io */ - struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */ - struct dm_io_client *client; /* Client memory handler */ -}; +int dm_io_get(unsigned int num_pages); +void dm_io_put(unsigned int num_pages); /* - * For async io calls, users can alternatively use the dm_io() function below - * and dm_io_client_create() to create private mempools for the client. + * Synchronous IO. * - * Create/destroy may block. + * Please ensure that the rw flag in the next two functions is + * either READ or WRITE, ie. we don't take READA. Any + * regions with a zero count field will be ignored. */ -struct dm_io_client *dm_io_client_create(unsigned num_pages); -int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client); -void dm_io_client_destroy(struct dm_io_client *client); +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits); + +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits); + +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits); /* - * IO interface using private per-client pools. - * Each bit in the optional 'sync_error_bits' bitset indicates whether an - * error occurred doing io to the corresponding region. + * Aynchronous IO. + * + * The 'where' array may be safely allocated on the stack since + * the function takes a copy. */ -int dm_io(struct dm_io_request *io_req, unsigned num_regions, - struct io_region *region, unsigned long *sync_error_bits); +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context); + +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context); + +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context); #endif diff --git a/trunk/drivers/md/dm-log.c b/trunk/drivers/md/dm-log.c index a66428d860fe..6a9261351848 100644 --- a/trunk/drivers/md/dm-log.c +++ b/trunk/drivers/md/dm-log.c @@ -149,12 +149,9 @@ struct log_c { FORCESYNC, /* Force a sync to happen */ } sync; - struct dm_io_request io_req; - /* * Disk log fields */ - int log_dev_failed; struct dm_dev *log_dev; struct log_header header; @@ -202,20 +199,13 @@ static void header_from_disk(struct log_header *core, struct log_header *disk) core->nr_regions = le64_to_cpu(disk->nr_regions); } -static int rw_header(struct log_c *lc, int rw) -{ - lc->io_req.bi_rw = rw; - lc->io_req.mem.ptr.vma = lc->disk_header; - lc->io_req.notify.fn = NULL; - - return dm_io(&lc->io_req, 1, &lc->header_location, NULL); -} - static int read_header(struct log_c *log) { int r; + unsigned long ebits; - r = rw_header(log, READ); + r = dm_io_sync_vm(1, &log->header_location, READ, + log->disk_header, &ebits); if (r) return r; @@ -243,8 +233,11 @@ static int read_header(struct log_c *log) static inline int write_header(struct log_c *log) { + unsigned long ebits; + header_to_disk(&log->header, log->disk_header); - return rw_header(log, WRITE); + return dm_io_sync_vm(1, &log->header_location, WRITE, + log->disk_header, &ebits); } /*---------------------------------------------------------------- @@ -263,7 +256,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, uint32_t region_size; unsigned int region_count; size_t bitset_size, buf_size; - int r; if (argc < 1 || argc > 2) { DMWARN("wrong number of arguments to mirror log"); @@ -323,7 +315,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, lc->disk_header = NULL; } else { lc->log_dev = dev; - lc->log_dev_failed = 0; lc->header_location.bdev = lc->log_dev->bdev; lc->header_location.sector = 0; @@ -333,15 +324,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size, ti->limits.hardsect_size); lc->header_location.count = buf_size >> SECTOR_SHIFT; - lc->io_req.mem.type = DM_IO_VMA; - lc->io_req.client = dm_io_client_create(dm_div_up(buf_size, - PAGE_SIZE)); - if (IS_ERR(lc->io_req.client)) { - r = PTR_ERR(lc->io_req.client); - DMWARN("couldn't allocate disk io client"); - kfree(lc); - return -ENOMEM; - } lc->disk_header = vmalloc(buf_size); if (!lc->disk_header) { @@ -442,7 +424,6 @@ static void disk_dtr(struct dirty_log *log) dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); - dm_io_client_destroy(lc->io_req.client); destroy_log_context(lc); } @@ -456,15 +437,6 @@ static int count_bits32(uint32_t *addr, unsigned size) return count; } -static void fail_log_device(struct log_c *lc) -{ - if (lc->log_dev_failed) - return; - - lc->log_dev_failed = 1; - dm_table_event(lc->ti->table); -} - static int disk_resume(struct dirty_log *log) { int r; @@ -474,19 +446,8 @@ static int disk_resume(struct dirty_log *log) /* read the disk header */ r = read_header(lc); - if (r) { - DMWARN("%s: Failed to read header on mirror log device", - lc->log_dev->name); - fail_log_device(lc); - /* - * If the log device cannot be read, we must assume - * all regions are out-of-sync. If we simply return - * here, the state will be uninitialized and could - * lead us to return 'in-sync' status for regions - * that are actually 'out-of-sync'. - */ - lc->header.nr_regions = 0; - } + if (r) + return r; /* set or clear any new bits -- device has grown */ if (lc->sync == NOSYNC) @@ -511,14 +472,7 @@ static int disk_resume(struct dirty_log *log) lc->header.nr_regions = lc->region_count; /* write the new header */ - r = write_header(lc); - if (r) { - DMWARN("%s: Failed to write header on mirror log device", - lc->log_dev->name); - fail_log_device(lc); - } - - return r; + return write_header(lc); } static uint32_t core_get_region_size(struct dirty_log *log) @@ -562,9 +516,7 @@ static int disk_flush(struct dirty_log *log) return 0; r = write_header(lc); - if (r) - fail_log_device(lc); - else + if (!r) lc->touched = 0; return r; @@ -639,7 +591,6 @@ static int core_status(struct dirty_log *log, status_type_t status, switch(status) { case STATUSTYPE_INFO: - DMEMIT("1 %s", log->type->name); break; case STATUSTYPE_TABLE: @@ -655,17 +606,17 @@ static int disk_status(struct dirty_log *log, status_type_t status, char *result, unsigned int maxlen) { int sz = 0; + char buffer[16]; struct log_c *lc = log->context; switch(status) { case STATUSTYPE_INFO: - DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name, - lc->log_dev_failed ? 'D' : 'A'); break; case STATUSTYPE_TABLE: + format_dev_t(buffer, lc->log_dev->bdev->bd_dev); DMEMIT("%s %u %s %u ", log->type->name, - lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name, + lc->sync == DEFAULTSYNC ? 2 : 3, buffer, lc->region_size); DMEMIT_SYNC; } diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index de54b39e6ffe..3aa013506967 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -668,9 +668,6 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) return -EINVAL; } - m->hw_handler.md = dm_table_get_md(ti->table); - dm_put(m->hw_handler.md); - r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv); if (r) { dm_put_hw_handler(hwht); diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index ef124b71ccc8..23a642619bed 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -21,12 +21,16 @@ #include #define DM_MSG_PREFIX "raid1" -#define DM_IO_PAGES 64 - -#define DM_RAID1_HANDLE_ERRORS 0x01 +static struct workqueue_struct *_kmirrord_wq; +static struct work_struct _kmirrord_work; static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); +static inline void wake(void) +{ + queue_work(_kmirrord_wq, &_kmirrord_work); +} + /*----------------------------------------------------------------- * Region hash * @@ -121,23 +125,17 @@ struct mirror_set { struct list_head list; struct region_hash rh; struct kcopyd_client *kcopyd_client; - uint64_t features; spinlock_t lock; /* protects the next two lists */ struct bio_list reads; struct bio_list writes; - struct dm_io_client *io_client; - /* recovery */ region_t nr_regions; int in_sync; struct mirror *default_mirror; /* Default mirror */ - struct workqueue_struct *kmirrord_wq; - struct work_struct kmirrord_work; - unsigned int nr_mirrors; struct mirror mirror[0]; }; @@ -155,11 +153,6 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region) return region << rh->region_shift; } -static void wake(struct mirror_set *ms) -{ - queue_work(ms->kmirrord_wq, &ms->kmirrord_work); -} - /* FIXME move this */ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); @@ -405,7 +398,8 @@ static void rh_update_states(struct region_hash *rh) mempool_free(reg, rh->region_pool); } - rh->log->type->flush(rh->log); + if (!list_empty(&recovered)) + rh->log->type->flush(rh->log); list_for_each_entry_safe (reg, next, &clean, list) mempool_free(reg, rh->region_pool); @@ -477,7 +471,7 @@ static void rh_dec(struct region_hash *rh, region_t region) spin_unlock_irqrestore(&rh->region_lock, flags); if (should_wake) - wake(rh->ms); + wake(); } /* @@ -564,7 +558,7 @@ static void rh_recovery_end(struct region *reg, int success) list_add(®->list, ®->rh->recovered_regions); spin_unlock_irq(&rh->region_lock); - wake(rh->ms); + wake(); } static void rh_flush(struct region_hash *rh) @@ -598,7 +592,7 @@ static void rh_start_recovery(struct region_hash *rh) for (i = 0; i < MAX_RECOVERY; i++) up(&rh->recovery_count); - wake(rh->ms); + wake(); } /* @@ -741,7 +735,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads) /* * We can only read balance if the region is in sync. */ - if (rh_in_sync(&ms->rh, region, 1)) + if (rh_in_sync(&ms->rh, region, 0)) m = choose_mirror(ms, bio->bi_sector); else m = ms->default_mirror; @@ -798,14 +792,6 @@ static void do_write(struct mirror_set *ms, struct bio *bio) unsigned int i; struct io_region io[KCOPYD_MAX_REGIONS+1]; struct mirror *m; - struct dm_io_request io_req = { - .bi_rw = WRITE, - .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx, - .notify.fn = write_callback, - .notify.context = bio, - .client = ms->io_client, - }; for (i = 0; i < ms->nr_mirrors; i++) { m = ms->mirror + i; @@ -816,8 +802,9 @@ static void do_write(struct mirror_set *ms, struct bio *bio) } bio_set_ms(bio, ms); - - (void) dm_io(&io_req, ms->nr_mirrors, io, NULL); + dm_io_async_bvec(ms->nr_mirrors, io, WRITE, + bio->bi_io_vec + bio->bi_idx, + write_callback, bio); } static void do_writes(struct mirror_set *ms, struct bio_list *writes) @@ -883,10 +870,11 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) /*----------------------------------------------------------------- * kmirrord *---------------------------------------------------------------*/ -static void do_mirror(struct work_struct *work) +static LIST_HEAD(_mirror_sets); +static DECLARE_RWSEM(_mirror_sets_lock); + +static void do_mirror(struct mirror_set *ms) { - struct mirror_set *ms =container_of(work, struct mirror_set, - kmirrord_work); struct bio_list reads, writes; spin_lock(&ms->lock); @@ -902,6 +890,16 @@ static void do_mirror(struct work_struct *work) do_writes(ms, &writes); } +static void do_work(struct work_struct *ignored) +{ + struct mirror_set *ms; + + down_read(&_mirror_sets_lock); + list_for_each_entry (ms, &_mirror_sets, list) + do_mirror(ms); + up_read(&_mirror_sets_lock); +} + /*----------------------------------------------------------------- * Target functions *---------------------------------------------------------------*/ @@ -933,13 +931,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, ms->in_sync = 0; ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; - ms->io_client = dm_io_client_create(DM_IO_PAGES); - if (IS_ERR(ms->io_client)) { - ti->error = "Error creating dm_io client"; - kfree(ms); - return NULL; - } - if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { ti->error = "Error creating dirty region hash"; kfree(ms); @@ -955,7 +946,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, while (m--) dm_put_device(ti, ms->mirror[m].dev); - dm_io_client_destroy(ms->io_client); rh_exit(&ms->rh); kfree(ms); } @@ -988,6 +978,23 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, return 0; } +static int add_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_add_tail(&ms->list, &_mirror_sets); + up_write(&_mirror_sets_lock); + wake(); + + return 0; +} + +static void del_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_del(&ms->list); + up_write(&_mirror_sets_lock); +} + /* * Create dirty log: log_type #log_params */ @@ -1030,55 +1037,16 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, return dl; } -static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, - unsigned *args_used) -{ - unsigned num_features; - struct dm_target *ti = ms->ti; - - *args_used = 0; - - if (!argc) - return 0; - - if (sscanf(argv[0], "%u", &num_features) != 1) { - ti->error = "Invalid number of features"; - return -EINVAL; - } - - argc--; - argv++; - (*args_used)++; - - if (num_features > argc) { - ti->error = "Not enough arguments to support feature count"; - return -EINVAL; - } - - if (!strcmp("handle_errors", argv[0])) - ms->features |= DM_RAID1_HANDLE_ERRORS; - else { - ti->error = "Unrecognised feature requested"; - return -EINVAL; - } - - (*args_used)++; - - return 0; -} - /* * Construct a mirror mapping: * * log_type #log_params * #mirrors [mirror_path offset]{2,} - * [#features ] * * log_type is "core" or "disk" * #log_params is between 1 and 3 - * - * If present, features must be "handle_errors". */ +#define DM_IO_PAGES 64 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) { int r; @@ -1102,8 +1070,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) argv++, argc--; - if (argc < nr_mirrors * 2) { - ti->error = "Too few mirror arguments"; + if (argc != nr_mirrors * 2) { + ti->error = "Wrong number of mirror arguments"; dm_destroy_dirty_log(dl); return -EINVAL; } @@ -1128,37 +1096,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->private = ms; ti->split_io = ms->rh.region_size; - ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); - if (!ms->kmirrord_wq) { - DMERR("couldn't start kmirrord"); - free_context(ms, ti, m); - return -ENOMEM; - } - INIT_WORK(&ms->kmirrord_work, do_mirror); - - r = parse_features(ms, argc, argv, &args_used); - if (r) { - free_context(ms, ti, ms->nr_mirrors); - return r; - } - - argv += args_used; - argc -= args_used; - - if (argc) { - ti->error = "Too many mirror arguments"; - free_context(ms, ti, ms->nr_mirrors); - return -EINVAL; - } - r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); if (r) { - destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); return r; } - wake(ms); + add_mirror_set(ms); return 0; } @@ -1166,9 +1110,8 @@ static void mirror_dtr(struct dm_target *ti) { struct mirror_set *ms = (struct mirror_set *) ti->private; - flush_workqueue(ms->kmirrord_wq); + del_mirror_set(ms); kcopyd_client_destroy(ms->kcopyd_client); - destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); } @@ -1184,7 +1127,7 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw) spin_unlock(&ms->lock); if (should_wake) - wake(ms); + wake(); } /* @@ -1279,9 +1222,11 @@ static void mirror_resume(struct dm_target *ti) static int mirror_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { - unsigned int m, sz = 0; + unsigned int m, sz; struct mirror_set *ms = (struct mirror_set *) ti->private; + sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); + switch (type) { case STATUSTYPE_INFO: DMEMIT("%d ", ms->nr_mirrors); @@ -1292,21 +1237,13 @@ static int mirror_status(struct dm_target *ti, status_type_t type, (unsigned long long)ms->rh.log->type-> get_sync_count(ms->rh.log), (unsigned long long)ms->nr_regions); - - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); - break; case STATUSTYPE_TABLE: - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); - DMEMIT("%d", ms->nr_mirrors); for (m = 0; m < ms->nr_mirrors; m++) DMEMIT(" %s %llu", ms->mirror[m].dev->name, (unsigned long long)ms->mirror[m].offset); - - if (ms->features & DM_RAID1_HANDLE_ERRORS) - DMEMIT(" 1 handle_errors"); } return 0; @@ -1314,7 +1251,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type, static struct target_type mirror_target = { .name = "mirror", - .version = {1, 0, 3}, + .version = {1, 0, 2}, .module = THIS_MODULE, .ctr = mirror_ctr, .dtr = mirror_dtr, @@ -1333,11 +1270,20 @@ static int __init dm_mirror_init(void) if (r) return r; + _kmirrord_wq = create_singlethread_workqueue("kmirrord"); + if (!_kmirrord_wq) { + DMERR("couldn't start kmirrord"); + dm_dirty_log_exit(); + return r; + } + INIT_WORK(&_kmirrord_work, do_work); + r = dm_register_target(&mirror_target); if (r < 0) { DMERR("%s: Failed to register mirror target", mirror_target.name); dm_dirty_log_exit(); + destroy_workqueue(_kmirrord_wq); } return r; @@ -1351,6 +1297,7 @@ static void __exit dm_mirror_exit(void) if (r < 0) DMERR("%s: unregister failed %d", mirror_target.name, r); + destroy_workqueue(_kmirrord_wq); dm_dirty_log_exit(); } diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 2fc199b0016b..05befa91807a 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -425,15 +425,13 @@ static void close_dev(struct dm_dev *d, struct mapped_device *md) } /* - * If possible, this checks an area of a destination device is valid. + * If possible (ie. blk_size[major] is set), this checks an area + * of a destination device is valid. */ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) { - sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; - - if (!dev_size) - return 1; - + sector_t dev_size; + dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; return ((start < dev_size) && (len <= (dev_size - start))); } diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 2717a355dc5b..11a98df298ec 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -1236,7 +1236,6 @@ void dm_put(struct mapped_device *md) free_dev(md); } } -EXPORT_SYMBOL_GPL(dm_put); /* * Process the deferred bios diff --git a/trunk/drivers/md/kcopyd.c b/trunk/drivers/md/kcopyd.c index dbc234e3c69f..b46f6c575f7e 100644 --- a/trunk/drivers/md/kcopyd.c +++ b/trunk/drivers/md/kcopyd.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2002 Sistina Software (UK) Limited. - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. * @@ -46,8 +45,6 @@ struct kcopyd_client { unsigned int nr_pages; unsigned int nr_free_pages; - struct dm_io_client *io_client; - wait_queue_head_t destroyq; atomic_t nr_jobs; }; @@ -345,20 +342,16 @@ static void complete_io(unsigned long error, void *context) static int run_io_job(struct kcopyd_job *job) { int r; - struct dm_io_request io_req = { - .bi_rw = job->rw, - .mem.type = DM_IO_PAGE_LIST, - .mem.ptr.pl = job->pages, - .mem.offset = job->offset, - .notify.fn = complete_io, - .notify.context = job, - .client = job->kc->io_client, - }; if (job->rw == READ) - r = dm_io(&io_req, 1, &job->source, NULL); + r = dm_io_async(1, &job->source, job->rw, + job->pages, + job->offset, complete_io, job); + else - r = dm_io(&io_req, job->num_dests, job->dests, NULL); + r = dm_io_async(job->num_dests, job->dests, job->rw, + job->pages, + job->offset, complete_io, job); return r; } @@ -677,9 +670,8 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) return r; } - kc->io_client = dm_io_client_create(nr_pages); - if (IS_ERR(kc->io_client)) { - r = PTR_ERR(kc->io_client); + r = dm_io_get(nr_pages); + if (r) { client_free_pages(kc); kfree(kc); kcopyd_exit(); @@ -699,7 +691,7 @@ void kcopyd_client_destroy(struct kcopyd_client *kc) /* Wait for completion of all jobs submitted by this client. */ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); - dm_io_client_destroy(kc->io_client); + dm_io_put(kc->nr_pages); client_free_pages(kc); client_del(kc); kfree(kc); diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index c10ce91b64e9..2b4315d7e5d6 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -33,7 +33,6 @@ */ #include -#include #include #include #include @@ -274,7 +273,6 @@ static mddev_t * mddev_find(dev_t unit) atomic_set(&new->active, 1); spin_lock_init(&new->write_lock); init_waitqueue_head(&new->sb_wait); - new->reshape_position = MaxSector; new->queue = blk_alloc_queue(GFP_KERNEL); if (!new->queue) { @@ -591,41 +589,14 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2) return ret; } - -static u32 md_csum_fold(u32 csum) -{ - csum = (csum & 0xffff) + (csum >> 16); - return (csum & 0xffff) + (csum >> 16); -} - static unsigned int calc_sb_csum(mdp_super_t * sb) { - u64 newcsum = 0; - u32 *sb32 = (u32*)sb; - int i; unsigned int disk_csum, csum; disk_csum = sb->sb_csum; sb->sb_csum = 0; - - for (i = 0; i < MD_SB_BYTES/4 ; i++) - newcsum += sb32[i]; - csum = (newcsum & 0xffffffff) + (newcsum>>32); - - -#ifdef CONFIG_ALPHA - /* This used to use csum_partial, which was wrong for several - * reasons including that different results are returned on - * different architectures. It isn't critical that we get exactly - * the same return value as before (we always csum_fold before - * testing, and that removes any differences). However as we - * know that csum_partial always returned a 16bit value on - * alphas, do a fold to maximise conformity to previous behaviour. - */ - sb->sb_csum = md_csum_fold(disk_csum); -#else + csum = csum_partial((void *)sb, MD_SB_BYTES, 0); sb->sb_csum = disk_csum; -#endif return csum; } @@ -713,7 +684,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version if (sb->raid_disks <= 0) goto abort; - if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) { + if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) { printk(KERN_WARNING "md: invalid superblock checksum on %s\n", b); goto abort; @@ -723,17 +694,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version rdev->data_offset = 0; rdev->sb_size = MD_SB_BYTES; - if (sb->state & (1<level != 1 && sb->level != 4 - && sb->level != 5 && sb->level != 6 - && sb->level != 10) { - /* FIXME use a better test */ - printk(KERN_WARNING - "md: bitmaps not supported for this level.\n"); - goto abort; - } - } - if (sb->level == LEVEL_MULTIPATH) rdev->desc_nr = -1; else @@ -832,8 +792,16 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = MD_SB_DISKS; if (sb->state & (1<bitmap_file == NULL) + mddev->bitmap_file == NULL) { + if (mddev->level != 1 && mddev->level != 4 + && mddev->level != 5 && mddev->level != 6 + && mddev->level != 10) { + /* FIXME use a better test */ + printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + return -EINVAL; + } mddev->bitmap_offset = mddev->default_bitmap_offset; + } } else if (mddev->pers == NULL) { /* Insist on good event counter while assembling */ @@ -1090,18 +1058,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) bdevname(rdev->bdev,b)); return -EINVAL; } - if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) { - if (sb->level != cpu_to_le32(1) && - sb->level != cpu_to_le32(4) && - sb->level != cpu_to_le32(5) && - sb->level != cpu_to_le32(6) && - sb->level != cpu_to_le32(10)) { - printk(KERN_WARNING - "md: bitmaps not supported for this level.\n"); - return -EINVAL; - } - } - rdev->preferred_minor = 0xffff; rdev->data_offset = le64_to_cpu(sb->data_offset); atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); @@ -1185,9 +1141,14 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = (4096-256)/2; if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && - mddev->bitmap_file == NULL ) + mddev->bitmap_file == NULL ) { + if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 + && mddev->level != 10) { + printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + return -EINVAL; + } mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); - + } if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { mddev->reshape_position = le64_to_cpu(sb->reshape_position); mddev->delta_disks = le32_to_cpu(sb->delta_disks); @@ -2243,10 +2204,6 @@ static ssize_t layout_show(mddev_t *mddev, char *page) { /* just a number, not meaningful for all levels */ - if (mddev->reshape_position != MaxSector && - mddev->layout != mddev->new_layout) - return sprintf(page, "%d (%d)\n", - mddev->new_layout, mddev->layout); return sprintf(page, "%d\n", mddev->layout); } @@ -2255,16 +2212,13 @@ layout_store(mddev_t *mddev, const char *buf, size_t len) { char *e; unsigned long n = simple_strtoul(buf, &e, 10); + if (mddev->pers) + return -EBUSY; if (!*buf || (*e && *e != '\n')) return -EINVAL; - if (mddev->pers) - return -EBUSY; - if (mddev->reshape_position != MaxSector) - mddev->new_layout = n; - else - mddev->layout = n; + mddev->layout = n; return len; } static struct md_sysfs_entry md_layout = @@ -2276,10 +2230,6 @@ raid_disks_show(mddev_t *mddev, char *page) { if (mddev->raid_disks == 0) return 0; - if (mddev->reshape_position != MaxSector && - mddev->delta_disks != 0) - return sprintf(page, "%d (%d)\n", mddev->raid_disks, - mddev->raid_disks - mddev->delta_disks); return sprintf(page, "%d\n", mddev->raid_disks); } @@ -2297,11 +2247,7 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len) if (mddev->pers) rv = update_raid_disks(mddev, n); - else if (mddev->reshape_position != MaxSector) { - int olddisks = mddev->raid_disks - mddev->delta_disks; - mddev->delta_disks = n - olddisks; - mddev->raid_disks = n; - } else + else mddev->raid_disks = n; return rv ? rv : len; } @@ -2311,10 +2257,6 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store); static ssize_t chunk_size_show(mddev_t *mddev, char *page) { - if (mddev->reshape_position != MaxSector && - mddev->chunk_size != mddev->new_chunk) - return sprintf(page, "%d (%d)\n", mddev->new_chunk, - mddev->chunk_size); return sprintf(page, "%d\n", mddev->chunk_size); } @@ -2325,15 +2267,12 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len) char *e; unsigned long n = simple_strtoul(buf, &e, 10); + if (mddev->pers) + return -EBUSY; if (!*buf || (*e && *e != '\n')) return -EINVAL; - if (mddev->pers) - return -EBUSY; - else if (mddev->reshape_position != MaxSector) - mddev->new_chunk = n; - else - mddev->chunk_size = n; + mddev->chunk_size = n; return len; } static struct md_sysfs_entry md_chunk_size = @@ -2698,7 +2637,8 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) minor = simple_strtoul(buf, &e, 10); if (e==buf || (*e && *e != '\n') ) return -EINVAL; - if (major >= ARRAY_SIZE(super_types) || super_types[major].name == NULL) + if (major >= sizeof(super_types)/sizeof(super_types[0]) || + super_types[major].name == NULL) return -ENOENT; mddev->major_version = major; mddev->minor_version = minor; @@ -2919,37 +2859,6 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_suspend_hi = __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); -static ssize_t -reshape_position_show(mddev_t *mddev, char *page) -{ - if (mddev->reshape_position != MaxSector) - return sprintf(page, "%llu\n", - (unsigned long long)mddev->reshape_position); - strcpy(page, "none\n"); - return 5; -} - -static ssize_t -reshape_position_store(mddev_t *mddev, const char *buf, size_t len) -{ - char *e; - unsigned long long new = simple_strtoull(buf, &e, 10); - if (mddev->pers) - return -EBUSY; - if (buf == e || (*e && *e != '\n')) - return -EINVAL; - mddev->reshape_position = new; - mddev->delta_disks = 0; - mddev->new_level = mddev->level; - mddev->new_layout = mddev->layout; - mddev->new_chunk = mddev->chunk_size; - return len; -} - -static struct md_sysfs_entry md_reshape_position = -__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, - reshape_position_store); - static struct attribute *md_default_attrs[] = { &md_level.attr, @@ -2962,7 +2871,6 @@ static struct attribute *md_default_attrs[] = { &md_new_device.attr, &md_safe_delay.attr, &md_array_state.attr, - &md_reshape_position.attr, NULL, }; @@ -3501,7 +3409,6 @@ static int do_md_stop(mddev_t * mddev, int mode) mddev->size = 0; mddev->raid_disks = 0; mddev->recovery_cp = 0; - mddev->reshape_position = MaxSector; } else if (mddev->pers) printk(KERN_INFO "md: %s switched to read-only mode.\n", @@ -4112,7 +4019,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) if (info->raid_disks == 0) { /* just setting version number for superblock loading */ if (info->major_version < 0 || - info->major_version >= ARRAY_SIZE(super_types) || + info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || super_types[info->major_version].name == NULL) { /* maybe try to auto-load a module? */ printk(KERN_INFO @@ -5034,6 +4941,15 @@ static int md_seq_open(struct inode *inode, struct file *file) return error; } +static int md_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *m = file->private_data; + struct mdstat_info *mi = m->private; + m->private = NULL; + kfree(mi); + return seq_release(inode, file); +} + static unsigned int mdstat_poll(struct file *filp, poll_table *wait) { struct seq_file *m = filp->private_data; @@ -5055,7 +4971,7 @@ static const struct file_operations md_seq_fops = { .open = md_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = md_seq_release, .poll = mdstat_poll, }; @@ -5103,7 +5019,7 @@ static int is_mddev_idle(mddev_t *mddev) * * Note: the following is an unsigned comparison. */ - if ((long)curr_events - (long)rdev->last_events > 4096) { + if ((curr_events - rdev->last_events + 4096) > 8192) { rdev->last_events = curr_events; idle = 0; } diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 3a95cc5e029c..97ee870b265d 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -271,25 +271,21 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int */ update_head_pos(mirror, r1_bio); - if (uptodate) - set_bit(R1BIO_Uptodate, &r1_bio->state); - else { - /* If all other devices have failed, we want to return - * the error upwards rather than fail the last device. - * Here we redefine "uptodate" to mean "Don't want to retry" + if (uptodate || (conf->raid_disks - conf->mddev->degraded) <= 1) { + /* + * Set R1BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. */ - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); - if (r1_bio->mddev->degraded == conf->raid_disks || - (r1_bio->mddev->degraded == conf->raid_disks-1 && - !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) - uptodate = 1; - spin_unlock_irqrestore(&conf->device_lock, flags); - } + if (uptodate) + set_bit(R1BIO_Uptodate, &r1_bio->state); - if (uptodate) raid_end_bio_io(r1_bio); - else { + } else { /* * oops, read error: */ @@ -996,14 +992,13 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded++; - set_bit(Faulty, &rdev->flags); spin_unlock_irqrestore(&conf->device_lock, flags); /* * if recovery is running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); - } else - set_bit(Faulty, &rdev->flags); + } + set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 061375ee6592..8d59914f2057 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -353,8 +353,8 @@ static int grow_stripes(raid5_conf_t *conf, int num) struct kmem_cache *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev)); - sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev)); + sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); + sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev)); conf->active_name = 0; sc = kmem_cache_create(conf->cache_name[conf->active_name], sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), diff --git a/trunk/drivers/media/Kconfig b/trunk/drivers/media/Kconfig index 3a80e0cc7369..91d25798ae4a 100644 --- a/trunk/drivers/media/Kconfig +++ b/trunk/drivers/media/Kconfig @@ -3,7 +3,6 @@ # menu "Multimedia devices" - depends on HAS_IOMEM config VIDEO_DEV tristate "Video For Linux" diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 9200a30dd1b9..68ed3a788083 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -3,7 +3,7 @@ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) * see dvb-usb-init.c for copyright information. * - * This file contains functions for initializing the input-device and for handling remote-control-queries. + * This file contains functions for initializing the the input-device and for handling remote-control-queries. */ #include "dvb-usb-common.h" #include diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.c b/trunk/drivers/media/dvb/frontends/dib7000m.c index f64546c6aeb5..f5d40aa3d27f 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000m.c +++ b/trunk/drivers/media/dvb/frontends/dib7000m.c @@ -266,7 +266,7 @@ static int dib7000m_sad_calib(struct dib7000m_state *state) { /* internal */ -// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth +// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 diff --git a/trunk/drivers/media/dvb/frontends/dib7000p.c b/trunk/drivers/media/dvb/frontends/dib7000p.c index aece458cfe12..0349a4b5da3f 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000p.c +++ b/trunk/drivers/media/dvb/frontends/dib7000p.c @@ -223,7 +223,7 @@ static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) static int dib7000p_sad_calib(struct dib7000p_state *state) { /* internal */ -// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth +// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 diff --git a/trunk/drivers/media/dvb/frontends/tda10021.c b/trunk/drivers/media/dvb/frontends/tda10021.c index e725f612a6b7..110536843e8e 100644 --- a/trunk/drivers/media/dvb/frontends/tda10021.c +++ b/trunk/drivers/media/dvb/frontends/tda10021.c @@ -1,6 +1,6 @@ /* TDA10021 - Single Chip Cable Channel Receiver driver module - used on the Siemens DVB-C cards + used on the the Siemens DVB-C cards Copyright (C) 1999 Convergence Integrated Media GmbH Copyright (C) 2004 Markus Schulz diff --git a/trunk/drivers/media/dvb/frontends/ves1x93.c b/trunk/drivers/media/dvb/frontends/ves1x93.c index 23fd0303c91b..54d7b07571b8 100644 --- a/trunk/drivers/media/dvb/frontends/ves1x93.c +++ b/trunk/drivers/media/dvb/frontends/ves1x93.c @@ -306,7 +306,7 @@ static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status) * The ves1893 sometimes returns sync values that make no sense, * because, e.g., the SIGNAL bit is 0, while some of the higher * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?). - * Tests showed that the VITERBI and SYNC bits are returned + * Tests showed that the the VITERBI and SYNC bits are returned * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong. * If such a case occurs, we read the value again, until we get a * valid value. diff --git a/trunk/drivers/media/video/em28xx/em28xx-i2c.c b/trunk/drivers/media/video/em28xx/em28xx-i2c.c index 54ccc6e1f92e..563a8319e608 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-i2c.c +++ b/trunk/drivers/media/video/em28xx/em28xx-i2c.c @@ -70,7 +70,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); if (ret != 2 + len) { - em28xx_warn("writing to i2c device failed (error=%i)\n", ret); + em28xx_warn("writting to i2c device failed (error=%i)\n", ret); return -EIO; } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; diff --git a/trunk/drivers/media/video/em28xx/em28xx-video.c b/trunk/drivers/media/video/em28xx/em28xx-video.c index 2c7b158ce7e1..bec67609500f 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-video.c +++ b/trunk/drivers/media/video/em28xx/em28xx-video.c @@ -1729,7 +1729,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, endpoint = &interface->cur_altsetting->endpoint[1].desc; - /* check if the device has the iso in endpoint at the correct place */ + /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); diff --git a/trunk/drivers/media/video/pwc/philips.txt b/trunk/drivers/media/video/pwc/philips.txt index f9f3584281d8..f5e848410311 100644 --- a/trunk/drivers/media/video/pwc/philips.txt +++ b/trunk/drivers/media/video/pwc/philips.txt @@ -54,9 +54,9 @@ fps Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This parameter specifies the number of internal buffers to use for storing + This paramter specifies the number of internal buffers to use for storing frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarily busy. However, on slow machines it + the cam is a bit slow or momentarely busy. However, on slow machines it only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. @@ -209,7 +209,7 @@ trace 128 0x80 PWCX debugging Off - For example, to trace the open() & read() functions, sum 8 + 4 = 12, + For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, so you would supply trace=12 during insmod or modprobe. If you want to turn the initialization and probing tracing off, set trace=0. The default value for trace is 35 (0x23). diff --git a/trunk/drivers/media/video/usbvideo/vicam.c b/trunk/drivers/media/video/usbvideo/vicam.c index 982b115193f8..876fd2768242 100644 --- a/trunk/drivers/media/video/usbvideo/vicam.c +++ b/trunk/drivers/media/video/usbvideo/vicam.c @@ -28,7 +28,7 @@ * * Portions of this code were also copied from usbvideo.c * - * Special thanks to the whole team at Sourceforge for help making + * Special thanks to the the whole team at Sourceforge for help making * this driver become a reality. Notably: * Andy Armstrong who reverse engineered the color encoding and * Pavel Machek and Chris Cheney who worked on reverse engineering the diff --git a/trunk/drivers/message/fusion/Kconfig b/trunk/drivers/message/fusion/Kconfig index c88cc75ab49b..71037f91c222 100644 --- a/trunk/drivers/message/fusion/Kconfig +++ b/trunk/drivers/message/fusion/Kconfig @@ -1,6 +1,5 @@ menu "Fusion MPT device support" - depends on PCI config FUSION bool diff --git a/trunk/drivers/message/fusion/lsi/mpi_history.txt b/trunk/drivers/message/fusion/lsi/mpi_history.txt index ddc7ae029dd3..d6b4c607453b 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_history.txt +++ b/trunk/drivers/message/fusion/lsi/mpi_history.txt @@ -571,7 +571,7 @@ mpi_fc.h * 11-02-00 01.01.01 Original release for post 1.0 work * 12-04-00 01.01.02 Added messages for Common Transport Send and * Primitive Send. - * 01-09-01 01.01.03 Modified some of the new flags to have an MPI prefix + * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix * and modified the FcPrimitiveSend flags. * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger * field. diff --git a/trunk/drivers/message/fusion/mptbase.c b/trunk/drivers/message/fusion/mptbase.c index 5021d1a2a1d4..97471af4309c 100644 --- a/trunk/drivers/message/fusion/mptbase.c +++ b/trunk/drivers/message/fusion/mptbase.c @@ -3585,7 +3585,7 @@ initChainBuffers(MPT_ADAPTER *ioc) * index = chain_idx * * Calculate the number of chain buffers needed(plus 1) per I/O - * then multiply the maximum number of simultaneous cmds + * then multiply the the maximum number of simultaneous cmds * * num_sge = num sge in request frame + last chain buffer * scale = num sge per chain buffer if no chain element diff --git a/trunk/drivers/message/i2o/Kconfig b/trunk/drivers/message/i2o/Kconfig index f4ac21e5771e..6443392bffff 100644 --- a/trunk/drivers/message/i2o/Kconfig +++ b/trunk/drivers/message/i2o/Kconfig @@ -1,6 +1,5 @@ menu "I2O device support" - depends on PCI config I2O tristate "I2O support" diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index a20a51efe118..ab6e985275b2 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -3,7 +3,6 @@ # menu "Multifunction device drivers" - depends on HAS_IOMEM config MFD_SM501 tristate "Support for Silicon Motion SM501" diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 2f2fbffafbe0..877e7909a0e5 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -130,7 +130,7 @@ config SONY_LAPTOP Read for more information. -config SONYPI_COMPAT +config SONY_LAPTOP_OLD bool "Sonypi compatibility" depends on SONY_LAPTOP ---help--- diff --git a/trunk/drivers/misc/asus-laptop.c b/trunk/drivers/misc/asus-laptop.c index 4f9060a2a2f2..65c32a95e121 100644 --- a/trunk/drivers/misc/asus-laptop.c +++ b/trunk/drivers/misc/asus-laptop.c @@ -30,7 +30,7 @@ * Eric Burghard - LED display support for W1N * Josh Green - Light Sens support * Thomas Tuttle - His first patch for led support was very helpfull - * Sam Lin - GPS support + * */ #include @@ -48,7 +48,7 @@ #include #include -#define ASUS_LAPTOP_VERSION "0.42" +#define ASUS_LAPTOP_VERSION "0.41" #define ASUS_HOTK_NAME "Asus Laptop Support" #define ASUS_HOTK_CLASS "hotkey" @@ -83,7 +83,6 @@ #define PLED_ON 0x20 //Phone LED #define GLED_ON 0x40 //Gaming LED #define LCD_ON 0x80 //LCD backlight -#define GPS_ON 0x100 //GPS #define ASUS_LOG ASUS_HOTK_FILE ": " #define ASUS_ERR KERN_ERR ASUS_LOG @@ -149,7 +148,7 @@ ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V - S5A M5A z33A W1Jc W2V G1 */ + S5A M5A z33A W1Jc W2V */ "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ @@ -163,12 +162,6 @@ ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ -/* GPS */ -/* R2H use different handle for GPS on/off */ -ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ -ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ -ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); - /* * This is the main structure, we can use it to store anything interesting * about the hotk device @@ -285,28 +278,12 @@ static int read_wireless_status(int mask) return (hotk->status & mask) ? 1 : 0; } -static int read_gps_status(void) -{ - ulong status; - acpi_status rv = AE_OK; - - rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); - if (ACPI_FAILURE(rv)) - printk(ASUS_WARNING "Error reading GPS status\n"); - else - return status ? 1 : 0; - - return (hotk->status & GPS_ON) ? 1 : 0; -} - /* Generic LED functions */ static int read_status(int mask) { /* There is a special method for both wireless devices */ if (mask == BT_ON || mask == WL_ON) return read_wireless_status(mask); - else if (mask == GPS_ON) - return read_gps_status(); return (hotk->status & mask) ? 1 : 0; } @@ -322,10 +299,6 @@ static void write_status(acpi_handle handle, int out, int mask) case GLED_ON: out = (out & 0x1) + 1; break; - case GPS_ON: - handle = (out) ? gps_on_handle : gps_off_handle; - out = 0x02; - break; default: out &= 0x1; break; @@ -694,21 +667,6 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, return rv; } -/* - * GPS - */ -static ssize_t show_gps(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", read_status(GPS_ON)); -} - -static ssize_t store_gps(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_status(buf, count, NULL, GPS_ON); -} - static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { /* TODO Find a better way to handle events count. */ @@ -757,7 +715,6 @@ static ASUS_CREATE_DEVICE_ATTR(display); static ASUS_CREATE_DEVICE_ATTR(ledd); static ASUS_CREATE_DEVICE_ATTR(ls_switch); static ASUS_CREATE_DEVICE_ATTR(ls_level); -static ASUS_CREATE_DEVICE_ATTR(gps); static struct attribute *asuspf_attributes[] = { &dev_attr_infos.attr, @@ -767,7 +724,6 @@ static struct attribute *asuspf_attributes[] = { &dev_attr_ledd.attr, &dev_attr_ls_switch.attr, &dev_attr_ls_level.attr, - &dev_attr_gps.attr, NULL }; @@ -807,9 +763,6 @@ static void asus_hotk_add_fs(void) ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); } - - if (gps_status_handle && gps_on_handle && gps_off_handle) - ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); } static int asus_handle_init(char *name, acpi_handle * handle, @@ -937,13 +890,9 @@ static int asus_hotk_get_info(void) /* There is a lot of models with "ALSL", but a few get a real light sens, so we need to check it. */ - if (!ASUS_HANDLE_INIT(ls_switch)) + if (ASUS_HANDLE_INIT(ls_switch)) ASUS_HANDLE_INIT(ls_level); - ASUS_HANDLE_INIT(gps_on); - ASUS_HANDLE_INIT(gps_off); - ASUS_HANDLE_INIT(gps_status); - kfree(model); return AE_OK; @@ -1001,7 +950,7 @@ static int asus_hotk_add(struct acpi_device *device) * We install the handler, it will receive the hotk in parameter, so, we * could add other data to the hotk struct */ - status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, + status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify, hotk); if (ACPI_FAILURE(status)) printk(ASUS_ERR "Error installing notify handler\n"); @@ -1032,9 +981,6 @@ static int asus_hotk_add(struct acpi_device *device) if (ls_level_handle) set_light_sens_level(hotk->light_level); - /* GPS is on by default */ - write_status(NULL, 1, GPS_ON); - end: if (result) { kfree(hotk->name); @@ -1051,7 +997,7 @@ static int asus_hotk_remove(struct acpi_device *device, int type) if (!device || !acpi_driver_data(device)) return -EINVAL; - status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, + status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify); if (ACPI_FAILURE(status)) printk(ASUS_ERR "Error removing notify handler\n"); diff --git a/trunk/drivers/misc/msi-laptop.c b/trunk/drivers/misc/msi-laptop.c index 41e901f53e7c..68c4b58525ba 100644 --- a/trunk/drivers/misc/msi-laptop.c +++ b/trunk/drivers/misc/msi-laptop.c @@ -85,7 +85,7 @@ static int set_lcd_level(int level) buf[0] = 0x80; buf[1] = (u8) (level*31); - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0, 1); + return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0); } static int get_lcd_level(void) @@ -93,7 +93,7 @@ static int get_lcd_level(void) u8 wdata = 0, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); if (result < 0) return result; @@ -105,7 +105,7 @@ static int get_auto_brightness(void) u8 wdata = 4, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); if (result < 0) return result; @@ -119,14 +119,14 @@ static int set_auto_brightness(int enable) wdata[0] = 4; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1); if (result < 0) return result; wdata[0] = 0x84; wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0); - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); + return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0); } static int get_wireless_state(int *wlan, int *bluetooth) @@ -134,7 +134,7 @@ static int get_wireless_state(int *wlan, int *bluetooth) u8 wdata = 0, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1); if (result < 0) return -1; diff --git a/trunk/drivers/misc/sony-laptop.c b/trunk/drivers/misc/sony-laptop.c index 8ee0321ef1c8..c15c1f61bd1b 100644 --- a/trunk/drivers/misc/sony-laptop.c +++ b/trunk/drivers/misc/sony-laptop.c @@ -63,7 +63,7 @@ #include #include #include -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD #include #include #endif @@ -114,7 +114,7 @@ MODULE_PARM_DESC(camera, "set this to 1 to enable Motion Eye camera controls " "(only use it if you have a C1VE or C1VN model)"); -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD static int minor = -1; module_param(minor, int, 0); MODULE_PARM_DESC(minor, @@ -1504,7 +1504,7 @@ static struct attribute_group spic_attribute_group = { }; /******** SONYPI compatibility **********/ -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD /* battery / brightness / temperature addresses */ #define SONYPI_BAT_FLAGS 0x81 @@ -1798,7 +1798,7 @@ static void sonypi_compat_exit(void) static int sonypi_compat_init(void) { return 0; } static void sonypi_compat_exit(void) { } static void sonypi_compat_report_event(u8 event) { } -#endif /* CONFIG_SONYPI_COMPAT */ +#endif /* CONFIG_SONY_LAPTOP_OLD */ /* * ACPI callbacks diff --git a/trunk/drivers/misc/tifm_7xx1.c b/trunk/drivers/misc/tifm_7xx1.c index c08ad8f823d2..1ba6c085419a 100644 --- a/trunk/drivers/misc/tifm_7xx1.c +++ b/trunk/drivers/misc/tifm_7xx1.c @@ -105,8 +105,7 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) == TIFM_TYPE_XD) msleep(40); - writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00, - sock_addr + SOCK_CONTROL); + writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); /* wait for power to stabilize */ msleep(20); for (cnt = 16; cnt <= 256; cnt <<= 1) { @@ -123,12 +122,6 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; } -inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr) -{ - writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL), - sock_addr + SOCK_CONTROL); -} - inline static char __iomem * tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) { @@ -140,7 +133,6 @@ static void tifm_7xx1_switch_media(struct work_struct *work) struct tifm_adapter *fm = container_of(work, struct tifm_adapter, media_switcher); struct tifm_dev *sock; - char __iomem *sock_addr; unsigned long flags; unsigned char media_id; unsigned int socket_change_set, cnt; @@ -166,12 +158,11 @@ static void tifm_7xx1_switch_media(struct work_struct *work) "%s : demand removing card from socket %u:%u\n", fm->cdev.class_id, fm->id, cnt); fm->sockets[cnt] = NULL; - sock_addr = sock->addr; spin_unlock_irqrestore(&fm->lock, flags); device_unregister(&sock->dev); spin_lock_irqsave(&fm->lock, flags); - tifm_7xx1_sock_power_off(sock_addr); - writel(0x0e00, sock_addr + SOCK_CONTROL); + writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt) + + SOCK_CONTROL); } spin_unlock_irqrestore(&fm->lock, flags); @@ -214,16 +205,8 @@ static void tifm_7xx1_switch_media(struct work_struct *work) static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) { - struct tifm_adapter *fm = pci_get_drvdata(dev); - int cnt; - dev_dbg(&dev->dev, "suspending host\n"); - for (cnt = 0; cnt < fm->num_sockets; cnt++) { - if (fm->sockets[cnt]) - tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr); - } - pci_save_state(dev); pci_enable_wake(dev, pci_choose_state(dev, state), 0); pci_disable_device(dev); @@ -374,7 +357,6 @@ static int tifm_7xx1_probe(struct pci_dev *dev, static void tifm_7xx1_remove(struct pci_dev *dev) { struct tifm_adapter *fm = pci_get_drvdata(dev); - int cnt; fm->eject = tifm_7xx1_dummy_eject; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); @@ -383,9 +365,6 @@ static void tifm_7xx1_remove(struct pci_dev *dev) tifm_remove_adapter(fm); - for (cnt = 0; cnt < fm->num_sockets; cnt++) - tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); - pci_set_drvdata(dev, NULL); iounmap(fm->addr); diff --git a/trunk/drivers/mmc/Kconfig b/trunk/drivers/mmc/Kconfig index c0b41e8bcd9d..6c97491543db 100644 --- a/trunk/drivers/mmc/Kconfig +++ b/trunk/drivers/mmc/Kconfig @@ -2,9 +2,10 @@ # MMC subsystem configuration # -menuconfig MMC - tristate "MMC/SD card support" - depends on HAS_IOMEM +menu "MMC/SD Card support" + +config MMC + tristate "MMC support" help MMC is the "multi-media card" bus protocol. @@ -18,12 +19,10 @@ config MMC_DEBUG This is an option for use by developers; most people should say N here. This enables MMC core and driver debugging. -if MMC - source "drivers/mmc/core/Kconfig" source "drivers/mmc/card/Kconfig" source "drivers/mmc/host/Kconfig" -endif # MMC +endmenu diff --git a/trunk/drivers/mmc/card/Kconfig b/trunk/drivers/mmc/card/Kconfig index 9320a8c73239..01a9fd376a1f 100644 --- a/trunk/drivers/mmc/card/Kconfig +++ b/trunk/drivers/mmc/card/Kconfig @@ -3,10 +3,11 @@ # comment "MMC/SD Card Drivers" + depends MMC config MMC_BLOCK tristate "MMC block device driver" - depends on BLOCK + depends on MMC && BLOCK default y help Say Y here to enable the MMC block device driver support. diff --git a/trunk/drivers/mmc/core/Kconfig b/trunk/drivers/mmc/core/Kconfig index ab37a6d9d32a..94222b9a15ea 100644 --- a/trunk/drivers/mmc/core/Kconfig +++ b/trunk/drivers/mmc/core/Kconfig @@ -4,6 +4,7 @@ config MMC_UNSAFE_RESUME bool "Allow unsafe resume (DANGEROUS)" + depends on MMC != n help If you say Y here, the MMC layer will assume that all cards stayed in their respective slots during the suspend. The diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 7385acfa1dd9..72c7cf4a9f9d 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -500,10 +500,9 @@ void __mmc_release_bus(struct mmc_host *host) void mmc_detect_change(struct mmc_host *host, unsigned long delay) { #ifdef CONFIG_MMC_DEBUG - unsigned long flags; - spin_lock_irqsave(&host->lock, flags); + mmc_claim_host(host); BUG_ON(host->removed); - spin_unlock_irqrestore(&host->lock, flags); + mmc_release_host(host); #endif mmc_schedule_delayed_work(&host->detect, delay); @@ -626,10 +625,9 @@ EXPORT_SYMBOL(mmc_add_host); void mmc_remove_host(struct mmc_host *host) { #ifdef CONFIG_MMC_DEBUG - unsigned long flags; - spin_lock_irqsave(&host->lock, flags); + mmc_claim_host(host); host->removed = 1; - spin_unlock_irqrestore(&host->lock, flags); + mmc_release_host(host); #endif mmc_flush_scheduled_work(); diff --git a/trunk/drivers/mmc/host/Kconfig b/trunk/drivers/mmc/host/Kconfig index e23082fe88d0..ed4deab2203d 100644 --- a/trunk/drivers/mmc/host/Kconfig +++ b/trunk/drivers/mmc/host/Kconfig @@ -3,10 +3,11 @@ # comment "MMC/SD Host Controller Drivers" + depends on MMC config MMC_ARMMMCI tristate "ARM AMBA Multimedia Card Interface support" - depends on ARM_AMBA + depends on ARM_AMBA && MMC help This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card Interface (PL180 and PL181) support. If you have an ARM(R) @@ -16,7 +17,7 @@ config MMC_ARMMMCI config MMC_PXA tristate "Intel PXA25x/26x/27x Multimedia Card Interface support" - depends on ARCH_PXA + depends on ARCH_PXA && MMC help This selects the Intel(R) PXA(R) Multimedia card Interface. If you have a PXA(R) platform with a Multimedia Card slot, @@ -26,7 +27,7 @@ config MMC_PXA config MMC_SDHCI tristate "Secure Digital Host Controller Interface support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + depends on PCI && MMC && EXPERIMENTAL help This select the generic Secure Digital Host Controller Interface. It is used by manufacturers such as Texas Instruments(R), Ricoh(R) @@ -37,7 +38,7 @@ config MMC_SDHCI config MMC_OMAP tristate "TI OMAP Multimedia Card Interface support" - depends on ARCH_OMAP + depends on ARCH_OMAP && MMC select TPS65010 if MACH_OMAP_H2 help This selects the TI OMAP Multimedia card Interface. @@ -48,7 +49,7 @@ config MMC_OMAP config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" - depends on ISA_DMA_API + depends on MMC && ISA_DMA_API help This selects the Winbond(R) W83L51xD Secure digital and Multimedia card Interface. @@ -59,7 +60,7 @@ config MMC_WBSD config MMC_AU1X tristate "Alchemy AU1XX0 MMC Card Interface support" - depends on SOC_AU1200 + depends on MMC && SOC_AU1200 help This selects the AMD Alchemy(R) Multimedia card interface. If you have a Alchemy platform with a MMC slot, say Y or M here. @@ -68,7 +69,7 @@ config MMC_AU1X config MMC_AT91 tristate "AT91 SD/MMC Card Interface support" - depends on ARCH_AT91 + depends on ARCH_AT91 && MMC help This selects the AT91 MCI controller. @@ -76,7 +77,7 @@ config MMC_AT91 config MMC_IMX tristate "Motorola i.MX Multimedia Card Interface support" - depends on ARCH_IMX + depends on ARCH_IMX && MMC help This selects the Motorola i.MX Multimedia card Interface. If you have a i.MX platform with a Multimedia Card slot, @@ -86,7 +87,7 @@ config MMC_IMX config MMC_TIFM_SD tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI + depends on MMC && EXPERIMENTAL && PCI select TIFM_CORE help Say Y here if you want to be able to access MMC/SD cards with diff --git a/trunk/drivers/mmc/host/tifm_sd.c b/trunk/drivers/mmc/host/tifm_sd.c index 8b736e968447..7511f961c67b 100644 --- a/trunk/drivers/mmc/host/tifm_sd.c +++ b/trunk/drivers/mmc/host/tifm_sd.c @@ -1021,6 +1021,10 @@ static void tifm_sd_remove(struct tifm_dev *sock) mmc_remove_host(mmc); dev_dbg(&sock->dev, "after remove\n"); + /* The meaning of the bit majority in this constant is unknown. */ + writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), + sock->addr + SOCK_CONTROL); + mmc_free_host(mmc); } @@ -1028,7 +1032,14 @@ static void tifm_sd_remove(struct tifm_dev *sock) static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) { - return mmc_suspend_host(tifm_get_drvdata(sock), state); + struct mmc_host *mmc = tifm_get_drvdata(sock); + int rc; + + rc = mmc_suspend_host(mmc, state); + /* The meaning of the bit majority in this constant is unknown. */ + writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), + sock->addr + SOCK_CONTROL); + return rc; } static int tifm_sd_resume(struct tifm_dev *sock) diff --git a/trunk/drivers/mtd/Kconfig b/trunk/drivers/mtd/Kconfig index fbec8cd55e38..c1b47db29bd2 100644 --- a/trunk/drivers/mtd/Kconfig +++ b/trunk/drivers/mtd/Kconfig @@ -2,7 +2,6 @@ menuconfig MTD tristate "Memory Technology Device (MTD) support" - depends on HAS_IOMEM help Memory Technology Devices are flash, RAM and similar chips, often used for solid state file systems on embedded devices. This option diff --git a/trunk/drivers/mtd/chips/Kconfig b/trunk/drivers/mtd/chips/Kconfig index 479d32b57a1e..d28e0fc85e12 100644 --- a/trunk/drivers/mtd/chips/Kconfig +++ b/trunk/drivers/mtd/chips/Kconfig @@ -1,4 +1,5 @@ # drivers/mtd/chips/Kconfig +# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $ menu "RAM/ROM/Flash chip drivers" depends on MTD!=n @@ -230,6 +231,45 @@ config MTD_ABSENT the system regardless of media presence. Device nodes created with this driver will return -ENODEV upon access. +config MTD_OBSOLETE_CHIPS + bool "Older (theoretically obsoleted now) drivers for non-CFI chips" + help + This option does not enable any code directly, but will allow you to + select some other chip drivers which are now considered obsolete, + because the generic CONFIG_JEDECPROBE code above should now detect + the chips which are supported by these drivers, and allow the generic + CFI-compatible drivers to drive the chips. Say 'N' here unless you have + already tried the CONFIG_JEDECPROBE method and reported its failure + to the MTD mailing list at + +config MTD_AMDSTD + tristate "AMD compatible flash chip support (non-CFI)" + depends on MTD_OBSOLETE_CHIPS && BROKEN + help + This option enables support for flash chips using AMD-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_AMDSTD option. + + It also works on AMD compatible chips that do conform to CFI. + +config MTD_SHARP + tristate "pre-CFI Sharp chip support" + depends on MTD_OBSOLETE_CHIPS + help + This option enables support for flash chips using Sharp-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_INTELxxx options. + +config MTD_JEDEC + tristate "JEDEC device support" + depends on MTD_OBSOLETE_CHIPS && BROKEN + help + Enable older JEDEC flash interface devices for self + programming flash. It is commonly used in older AMD chips. It is + only called JEDEC because the JEDEC association + distributes the identification codes for the + chips. + config MTD_XIP bool "XIP aware MTD support" depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP diff --git a/trunk/drivers/mtd/chips/Makefile b/trunk/drivers/mtd/chips/Makefile index 36582412ccda..75bc1c2a0f43 100644 --- a/trunk/drivers/mtd/chips/Makefile +++ b/trunk/drivers/mtd/chips/Makefile @@ -1,15 +1,19 @@ # # linux/drivers/chips/Makefile # +# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $ obj-$(CONFIG_MTD) += chipreg.o +obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o +obj-$(CONFIG_MTD_JEDEC) += jedec.o obj-$(CONFIG_MTD_JEDECPROBE) += jedec_probe.o obj-$(CONFIG_MTD_RAM) += map_ram.o obj-$(CONFIG_MTD_ROM) += map_rom.o +obj-$(CONFIG_MTD_SHARP) += sharp.o obj-$(CONFIG_MTD_ABSENT) += map_absent.o diff --git a/trunk/drivers/mtd/chips/amd_flash.c b/trunk/drivers/mtd/chips/amd_flash.c new file mode 100644 index 000000000000..e7999f15d85a --- /dev/null +++ b/trunk/drivers/mtd/chips/amd_flash.c @@ -0,0 +1,1396 @@ +/* + * MTD map driver for AMD compatible flash chips (non-CFI) + * + * Author: Jonas Holmberg + * + * $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $ + * + * Copyright (c) 2001 Axis Communications AB + * + * This file is under GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* There's no limit. It exists only to avoid realloc. */ +#define MAX_AMD_CHIPS 8 + +#define DEVICE_TYPE_X8 (8 / 8) +#define DEVICE_TYPE_X16 (16 / 8) +#define DEVICE_TYPE_X32 (32 / 8) + +/* Addresses */ +#define ADDR_MANUFACTURER 0x0000 +#define ADDR_DEVICE_ID 0x0001 +#define ADDR_SECTOR_LOCK 0x0002 +#define ADDR_HANDSHAKE 0x0003 +#define ADDR_UNLOCK_1 0x0555 +#define ADDR_UNLOCK_2 0x02AA + +/* Commands */ +#define CMD_UNLOCK_DATA_1 0x00AA +#define CMD_UNLOCK_DATA_2 0x0055 +#define CMD_MANUFACTURER_UNLOCK_DATA 0x0090 +#define CMD_UNLOCK_BYPASS_MODE 0x0020 +#define CMD_PROGRAM_UNLOCK_DATA 0x00A0 +#define CMD_RESET_DATA 0x00F0 +#define CMD_SECTOR_ERASE_UNLOCK_DATA 0x0080 +#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x0030 + +#define CMD_UNLOCK_SECTOR 0x0060 + +/* Manufacturers */ +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_ATMEL 0x001F +#define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_ST 0x0020 +#define MANUFACTURER_SST 0x00BF +#define MANUFACTURER_TOSHIBA 0x0098 + +/* AMD */ +#define AM29F800BB 0x2258 +#define AM29F800BT 0x22D6 +#define AM29LV800BB 0x225B +#define AM29LV800BT 0x22DA +#define AM29LV160DT 0x22C4 +#define AM29LV160DB 0x2249 +#define AM29BDS323D 0x22D1 + +/* Atmel */ +#define AT49xV16x 0x00C0 +#define AT49xV16xT 0x00C2 + +/* Fujitsu */ +#define MBM29LV160TE 0x22C4 +#define MBM29LV160BE 0x2249 +#define MBM29LV800BB 0x225B + +/* ST - www.st.com */ +#define M29W800T 0x00D7 +#define M29W160DT 0x22C4 +#define M29W160DB 0x2249 + +/* SST */ +#define SST39LF800 0x2781 +#define SST39LF160 0x2782 + +/* Toshiba */ +#define TC58FVT160 0x00C2 +#define TC58FVB160 0x0043 + +#define D6_MASK 0x40 + +struct amd_flash_private { + int device_type; + int interleave; + int numchips; + unsigned long chipshift; + struct flchip chips[0]; +}; + +struct amd_flash_info { + const __u16 mfr_id; + const __u16 dev_id; + const char *name; + const u_long size; + const int numeraseregions; + const struct mtd_erase_region_info regions[4]; +}; + + + +static int amd_flash_read(struct mtd_info *, loff_t, size_t, size_t *, + u_char *); +static int amd_flash_write(struct mtd_info *, loff_t, size_t, size_t *, + const u_char *); +static int amd_flash_erase(struct mtd_info *, struct erase_info *); +static void amd_flash_sync(struct mtd_info *); +static int amd_flash_suspend(struct mtd_info *); +static void amd_flash_resume(struct mtd_info *); +static void amd_flash_destroy(struct mtd_info *); +static struct mtd_info *amd_flash_probe(struct map_info *map); + + +static struct mtd_chip_driver amd_flash_chipdrv = { + .probe = amd_flash_probe, + .destroy = amd_flash_destroy, + .name = "amd_flash", + .module = THIS_MODULE +}; + +static inline __u32 wide_read(struct map_info *map, __u32 addr) +{ + if (map->buswidth == 1) { + return map_read8(map, addr); + } else if (map->buswidth == 2) { + return map_read16(map, addr); + } else if (map->buswidth == 4) { + return map_read32(map, addr); + } + + return 0; +} + +static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) +{ + if (map->buswidth == 1) { + map_write8(map, val, addr); + } else if (map->buswidth == 2) { + map_write16(map, val, addr); + } else if (map->buswidth == 4) { + map_write32(map, val, addr); + } +} + +static inline __u32 make_cmd(struct map_info *map, __u32 cmd) +{ + const struct amd_flash_private *private = map->fldrv_priv; + if ((private->interleave == 2) && + (private->device_type == DEVICE_TYPE_X16)) { + cmd |= (cmd << 16); + } + + return cmd; +} + +static inline void send_unlock(struct map_info *map, unsigned long base) +{ + wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1, + base + (map->buswidth * ADDR_UNLOCK_1)); + wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2, + base + (map->buswidth * ADDR_UNLOCK_2)); +} + +static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), + base + (map->buswidth * ADDR_UNLOCK_1)); +} + +static inline void send_cmd_to_addr(struct map_info *map, unsigned long base, + __u32 cmd, unsigned long addr) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), addr); +} + +static inline int flash_is_busy(struct map_info *map, unsigned long addr, + int interleave) +{ + + if ((interleave == 2) && (map->buswidth == 4)) { + __u32 read1, read2; + + read1 = wide_read(map, addr); + read2 = wide_read(map, addr); + + return (((read1 >> 16) & D6_MASK) != + ((read2 >> 16) & D6_MASK)) || + (((read1 & 0xffff) & D6_MASK) != + ((read2 & 0xffff) & D6_MASK)); + } + + return ((wide_read(map, addr) & D6_MASK) != + (wide_read(map, addr) & D6_MASK)); +} + +static inline void unlock_sector(struct map_info *map, unsigned long sect_addr, + int unlock) +{ + /* Sector lock address. A6 = 1 for unlock, A6 = 0 for lock */ + int SLA = unlock ? + (sect_addr | (0x40 * map->buswidth)) : + (sect_addr & ~(0x40 * map->buswidth)) ; + + __u32 cmd = make_cmd(map, CMD_UNLOCK_SECTOR); + + wide_write(map, make_cmd(map, CMD_RESET_DATA), 0); + wide_write(map, cmd, SLA); /* 1st cycle: write cmd to any address */ + wide_write(map, cmd, SLA); /* 2nd cycle: write cmd to any address */ + wide_write(map, cmd, SLA); /* 3rd cycle: write cmd to SLA */ +} + +static inline int is_sector_locked(struct map_info *map, + unsigned long sect_addr) +{ + int status; + + wide_write(map, CMD_RESET_DATA, 0); + send_cmd(map, sect_addr, CMD_MANUFACTURER_UNLOCK_DATA); + + /* status is 0x0000 for unlocked and 0x0001 for locked */ + status = wide_read(map, sect_addr + (map->buswidth * ADDR_SECTOR_LOCK)); + wide_write(map, CMD_RESET_DATA, 0); + return status; +} + +static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len, + int is_unlock) +{ + struct map_info *map; + struct mtd_erase_region_info *merip; + int eraseoffset, erasesize, eraseblocks; + int i; + int retval = 0; + int lock_status; + + map = mtd->priv; + + /* Pass the whole chip through sector by sector and check for each + sector if the sector and the given interval overlap */ + for(i = 0; i < mtd->numeraseregions; i++) { + merip = &mtd->eraseregions[i]; + + eraseoffset = merip->offset; + erasesize = merip->erasesize; + eraseblocks = merip->numblocks; + + if (ofs > eraseoffset + erasesize) + continue; + + while (eraseblocks > 0) { + if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) { + unlock_sector(map, eraseoffset, is_unlock); + + lock_status = is_sector_locked(map, eraseoffset); + + if (is_unlock && lock_status) { + printk("Cannot unlock sector at address %x length %xx\n", + eraseoffset, merip->erasesize); + retval = -1; + } else if (!is_unlock && !lock_status) { + printk("Cannot lock sector at address %x length %x\n", + eraseoffset, merip->erasesize); + retval = -1; + } + } + eraseoffset += erasesize; + eraseblocks --; + } + } + return retval; +} + +static int amd_flash_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return amd_flash_do_unlock(mtd, ofs, len, 1); +} + +static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return amd_flash_do_unlock(mtd, ofs, len, 0); +} + + +/* + * Reads JEDEC manufacturer ID and device ID and returns the index of the first + * matching table entry (-1 if not found or alias for already found chip). + */ +static int probe_new_chip(struct mtd_info *mtd, __u32 base, + struct flchip *chips, + struct amd_flash_private *private, + const struct amd_flash_info *table, int table_size) +{ + __u32 mfr_id; + __u32 dev_id; + struct map_info *map = mtd->priv; + struct amd_flash_private temp; + int i; + + temp.device_type = DEVICE_TYPE_X16; // Assume X16 (FIXME) + temp.interleave = 2; + map->fldrv_priv = &temp; + + /* Enter autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA); + + mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER)); + dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID)); + + if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) && + ((dev_id >> 16) == (dev_id & 0xffff))) { + mfr_id &= 0xffff; + dev_id &= 0xffff; + } else { + temp.interleave = 1; + } + + for (i = 0; i < table_size; i++) { + if ((mfr_id == table[i].mfr_id) && + (dev_id == table[i].dev_id)) { + if (chips) { + int j; + + /* Is this an alias for an already found chip? + * In that case that chip should be in + * autoselect mode now. + */ + for (j = 0; j < private->numchips; j++) { + __u32 mfr_id_other; + __u32 dev_id_other; + + mfr_id_other = + wide_read(map, chips[j].start + + (map->buswidth * + ADDR_MANUFACTURER + )); + dev_id_other = + wide_read(map, chips[j].start + + (map->buswidth * + ADDR_DEVICE_ID)); + if (temp.interleave == 2) { + mfr_id_other &= 0xffff; + dev_id_other &= 0xffff; + } + if ((mfr_id_other == mfr_id) && + (dev_id_other == dev_id)) { + + /* Exit autoselect mode. */ + send_cmd(map, base, + CMD_RESET_DATA); + + return -1; + } + } + + if (private->numchips == MAX_AMD_CHIPS) { + printk(KERN_WARNING + "%s: Too many flash chips " + "detected. Increase " + "MAX_AMD_CHIPS from %d.\n", + map->name, MAX_AMD_CHIPS); + + return -1; + } + + chips[private->numchips].start = base; + chips[private->numchips].state = FL_READY; + chips[private->numchips].mutex = + &chips[private->numchips]._spinlock; + private->numchips++; + } + + printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name, + temp.interleave, (table[i].size)/(1024*1024), + table[i].name, base); + + mtd->size += table[i].size * temp.interleave; + mtd->numeraseregions += table[i].numeraseregions; + + break; + } + } + + /* Exit autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + + if (i == table_size) { + printk(KERN_DEBUG "%s: unknown flash device at 0x%x, " + "mfr id 0x%x, dev id 0x%x\n", map->name, + base, mfr_id, dev_id); + map->fldrv_priv = NULL; + + return -1; + } + + private->device_type = temp.device_type; + private->interleave = temp.interleave; + + return i; +} + + + +static struct mtd_info *amd_flash_probe(struct map_info *map) +{ + static const struct amd_flash_info table[] = { + { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV160DT, + .name = "AMD AM29LV160DT", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV160DB, + .name = "AMD AM29LV160DB", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_TOSHIBA, + .dev_id = TC58FVT160, + .name = "Toshiba TC58FVT160", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV160TE, + .name = "Fujitsu MBM29LV160TE", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_TOSHIBA, + .dev_id = TC58FVB160, + .name = "Toshiba TC58FVB160", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV160BE, + .name = "Fujitsu MBM29LV160BE", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BB, + .name = "AMD AM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29F800BB, + .name = "AMD AM29F800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BT, + .name = "AMD AM29LV800BT", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29F800BT, + .name = "AMD AM29F800BT", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BB, + .name = "AMD AM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV800BB, + .name = "Fujitsu MBM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W800T, + .name = "ST M29W800T", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W160DT, + .name = "ST M29W160DT", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W160DB, + .name = "ST M29W160DB", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29BDS323D, + .name = "AMD AM29BDS323D", + .size = 0x00400000, + .numeraseregions = 3, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 }, + { .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x3f0000, .erasesize = 0x02000, .numblocks = 8 }, + } + }, { + .mfr_id = MANUFACTURER_ATMEL, + .dev_id = AT49xV16x, + .name = "Atmel AT49xV16x", + .size = 0x00200000, + .numeraseregions = 2, + .regions = { + { .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_ATMEL, + .dev_id = AT49xV16xT, + .name = "Atmel AT49xV16xT", + .size = 0x00200000, + .numeraseregions = 2, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 } + } + } + }; + + struct mtd_info *mtd; + struct flchip chips[MAX_AMD_CHIPS]; + int table_pos[MAX_AMD_CHIPS]; + struct amd_flash_private temp; + struct amd_flash_private *private; + u_long size; + unsigned long base; + int i; + int reg_idx; + int offset; + + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_WARNING + "%s: kmalloc failed for info structure\n", map->name); + return NULL; + } + mtd->priv = map; + + memset(&temp, 0, sizeof(temp)); + + printk("%s: Probing for AMD compatible flash...\n", map->name); + + if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, + ARRAY_SIZE(table))) + == -1) { + printk(KERN_WARNING + "%s: Found no AMD compatible device at location zero\n", + map->name); + kfree(mtd); + + return NULL; + } + + chips[0].start = 0; + chips[0].state = FL_READY; + chips[0].mutex = &chips[0]._spinlock; + temp.numchips = 1; + for (size = mtd->size; size > 1; size >>= 1) { + temp.chipshift++; + } + switch (temp.interleave) { + case 2: + temp.chipshift += 1; + break; + case 4: + temp.chipshift += 2; + break; + } + + /* Find out if there are any more chips in the map. */ + for (base = (1 << temp.chipshift); + base < map->size; + base += (1 << temp.chipshift)) { + int numchips = temp.numchips; + table_pos[numchips] = probe_new_chip(mtd, base, chips, + &temp, table, ARRAY_SIZE(table)); + } + + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * + mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk(KERN_WARNING "%s: Failed to allocate " + "memory for MTD erase region info\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return NULL; + } + + reg_idx = 0; + offset = 0; + for (i = 0; i < temp.numchips; i++) { + int dev_size; + int j; + + dev_size = 0; + for (j = 0; j < table[table_pos[i]].numeraseregions; j++) { + mtd->eraseregions[reg_idx].offset = offset + + (table[table_pos[i]].regions[j].offset * + temp.interleave); + mtd->eraseregions[reg_idx].erasesize = + table[table_pos[i]].regions[j].erasesize * + temp.interleave; + mtd->eraseregions[reg_idx].numblocks = + table[table_pos[i]].regions[j].numblocks; + if (mtd->erasesize < + mtd->eraseregions[reg_idx].erasesize) { + mtd->erasesize = + mtd->eraseregions[reg_idx].erasesize; + } + dev_size += mtd->eraseregions[reg_idx].erasesize * + mtd->eraseregions[reg_idx].numblocks; + reg_idx++; + } + offset += dev_size; + } + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + mtd->erase = amd_flash_erase; + mtd->read = amd_flash_read; + mtd->write = amd_flash_write; + mtd->sync = amd_flash_sync; + mtd->suspend = amd_flash_suspend; + mtd->resume = amd_flash_resume; + mtd->lock = amd_flash_lock; + mtd->unlock = amd_flash_unlock; + + private = kmalloc(sizeof(*private) + (sizeof(struct flchip) * + temp.numchips), GFP_KERNEL); + if (!private) { + printk(KERN_WARNING + "%s: kmalloc failed for private structure\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return NULL; + } + memcpy(private, &temp, sizeof(temp)); + memcpy(private->chips, chips, + sizeof(struct flchip) * private->numchips); + for (i = 0; i < private->numchips; i++) { + init_waitqueue_head(&private->chips[i].wq); + spin_lock_init(&private->chips[i]._spinlock); + } + + map->fldrv_priv = private; + + map->fldrv = &amd_flash_chipdrv; + + __module_get(THIS_MODULE); + return mtd; +} + + + +static inline int read_one_chip(struct map_info *map, struct flchip *chip, + loff_t adr, size_t len, u_char *buf) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo = jiffies + HZ; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk(KERN_INFO "%s: waiting for chip to read, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + adr += chip->start; + + chip->state = FL_READY; + + map_copy_from(map, buf, adr, len); + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + if ((from + len) > mtd->size) { + printk(KERN_WARNING "%s: read request past end of device " + "(0x%lx)\n", map->name, (unsigned long)from + len); + + return -EINVAL; + } + + /* Offset within the first chip that the first read should start. */ + chipnum = (from >> private->chipshift); + ofs = from - (chipnum << private->chipshift); + + *retlen = 0; + + while (len) { + unsigned long this_len; + + if (chipnum >= private->numchips) { + break; + } + + if ((len + ofs - 1) >> private->chipshift) { + this_len = (1 << private->chipshift) - ofs; + } else { + this_len = len; + } + + ret = read_one_chip(map, &private->chips[chipnum], ofs, + this_len, buf); + if (ret) { + break; + } + + *retlen += this_len; + len -= this_len; + buf += this_len; + + ofs = 0; + chipnum++; + } + + return ret; +} + + + +static int write_one_word(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + int times_left; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk("%s: waiting for chip to write, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + printk(KERN_INFO "%s: woke up to write\n", map->name); + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_WRITING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA); + wide_write(map, datum, adr); + + times_left = 500000; + while (times_left-- && flash_is_busy(map, adr, private->interleave)) { + if (need_resched()) { + spin_unlock_bh(chip->mutex); + schedule(); + spin_lock_bh(chip->mutex); + } + } + + if (!times_left) { + printk(KERN_WARNING "%s: write to 0x%lx timed out!\n", + map->name, adr); + ret = -EIO; + } else { + __u32 verify; + if ((verify = wide_read(map, adr)) != datum) { + printk(KERN_WARNING "%s: write to 0x%lx failed. " + "datum = %x, verify = %x\n", + map->name, adr, datum, verify); + ret = -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return ret; +} + + + +static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs; + unsigned long chipstart; + + *retlen = 0; + if (!len) { + return 0; + } + + chipnum = to >> private->chipshift; + ofs = to - (chipnum << private->chipshift); + chipstart = private->chips[chipnum].start; + + /* If it's not bus-aligned, do the first byte write. */ + if (ofs & (map->buswidth - 1)) { + unsigned long bus_ofs = ofs & ~(map->buswidth - 1); + int i = ofs - bus_ofs; + int n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map_copy_from(map, tmp_buf, + bus_ofs + private->chips[chipnum].start, + map->buswidth); + while (len && i < map->buswidth) + tmp_buf[i++] = buf[n++], len--; + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], bus_ofs, + datum); + if (ret) { + return ret; + } + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + } + } + + /* We are now aligned, write as much as possible. */ + while(len >= map->buswidth) { + __u32 datum; + + if (map->buswidth == 1) { + datum = *(__u8*)buf; + } else if (map->buswidth == 2) { + datum = *(__u16*)buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + ofs += map->buswidth; + buf += map->buswidth; + (*retlen) += map->buswidth; + len -= map->buswidth; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + chipstart = private->chips[chipnum].start; + } + } + + if (len & (map->buswidth - 1)) { + int i = 0, n = 0; + u_char tmp_buf[2]; + __u32 datum; + + map_copy_from(map, tmp_buf, + ofs + private->chips[chipnum].start, + map->buswidth); + while (len--) { + tmp_buf[i++] = buf[n++]; + } + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + (*retlen) += n; + } + + return 0; +} + + + +static inline int erase_one_block(struct map_info *map, struct flchip *chip, + unsigned long adr, u_long size) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_ERASING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA); + send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr); + + timeo = jiffies + (HZ * 20); + + spin_unlock_bh(chip->mutex); + msleep(1000); + spin_lock_bh(chip->mutex); + + while (flash_is_busy(map, adr, private->interleave)) { + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + printk(KERN_INFO "%s: erase suspended. Sleeping\n", + map->name); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + (HZ*2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING "%s: waiting for erase to complete " + "timed out.\n", map->name); + DISABLE_VPP(map); + + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + if (need_resched()) + schedule(); + else + udelay(1); + + spin_lock_bh(chip->mutex); + } + + /* Verify every single word */ + { + int address; + int error = 0; + __u8 verify; + + for (address = adr; address < (adr + size); address++) { + if ((verify = map_read8(map, address)) != 0xFF) { + error = 1; + break; + } + } + if (error) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING + "%s: verify error at 0x%x, size %ld.\n", + map->name, address, size); + DISABLE_VPP(map); + + return -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long adr, len; + int chipnum; + int ret = 0; + int i; + int first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) { + return -EINVAL; + } + + if ((instr->len + instr->addr) > mtd->size) { + return -EINVAL; + } + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while ((i < mtd->numeraseregions) && + (instr->addr >= regions[i].offset)) { + i++; + } + i--; + + /* OK, now i is pointing at the erase region in which this + * erase request starts. Check the start of the requested + * erase range is aligned with the erase size which is in + * effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) { + return -EINVAL; + } + + /* Remember the erase region we start on. */ + + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while ((i < mtd->numeraseregions) && + ((instr->addr + instr->len) >= regions[i].offset)) { + i++; + } + + /* As before, drop back one to point at the region in which + * the address actually falls. + */ + + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) { + return -EINVAL; + } + + chipnum = instr->addr >> private->chipshift; + adr = instr->addr - (chipnum << private->chipshift); + len = instr->len; + + i = first; + + while (len) { + ret = erase_one_block(map, &private->chips[chipnum], adr, + regions[i].erasesize); + + if (ret) { + return ret; + } + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if ((adr % (1 << private->chipshift)) == + ((regions[i].offset + (regions[i].erasesize * + regions[i].numblocks)) + % (1 << private->chipshift))) { + i++; + } + + if (adr >> private->chipshift) { + adr = 0; + chipnum++; + if (chipnum >= private->numchips) { + break; + } + } + } + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + + + +static void amd_flash_sync(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i = 0; !ret && (i < private->numchips); i++) { + chip = &private->chips[i]; + + retry: + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + spin_unlock_bh(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + for (i--; i >= 0; i--) { + chip = &private->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } +} + + + +static int amd_flash_suspend(struct mtd_info *mtd) +{ +printk("amd_flash_suspend(): not implemented!\n"); + return -EINVAL; +} + + + +static void amd_flash_resume(struct mtd_info *mtd) +{ +printk("amd_flash_resume(): not implemented!\n"); +} + + + +static void amd_flash_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + kfree(private); +} + +int __init amd_flash_init(void) +{ + register_mtd_chip_driver(&amd_flash_chipdrv); + return 0; +} + +void __exit amd_flash_exit(void) +{ + unregister_mtd_chip_driver(&amd_flash_chipdrv); +} + +module_init(amd_flash_init); +module_exit(amd_flash_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Holmberg "); +MODULE_DESCRIPTION("Old MTD chip driver for AMD flash chips"); diff --git a/trunk/drivers/mtd/chips/jedec.c b/trunk/drivers/mtd/chips/jedec.c new file mode 100644 index 000000000000..14e57b2bf842 --- /dev/null +++ b/trunk/drivers/mtd/chips/jedec.c @@ -0,0 +1,935 @@ + +/* JEDEC Flash Interface. + * This is an older type of interface for self programming flash. It is + * commonly use in older AMD chips and is obsolete compared with CFI. + * It is called JEDEC because the JEDEC association distributes the ID codes + * for the chips. + * + * See the AMD flash databook for information on how to operate the interface. + * + * This code does not support anything wider than 8 bit flash chips, I am + * not going to guess how to send commands to them, plus I expect they will + * all speak CFI.. + * + * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *jedec_probe(struct map_info *); +static int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len); +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr); +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf); + +static unsigned long my_bank_size; + +/* Listing of parts and sizes. We need this table to learn the sector + size of the chip and the total length */ +static const struct JEDECTable JEDEC_table[] = { + { + .jedec = 0x013D, + .name = "AMD Am29F017D", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01AD, + .name = "AMD Am29F016", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01D5, + .name = "AMD Am29F080", + .size = 1*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01A4, + .name = "AMD Am29F040", + .size = 512*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x20E3, + .name = "AMD Am29W040B", + .size = 512*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0xC2AD, + .name = "Macronix MX29F016", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { .jedec = 0x0 } +}; + +static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id); +static void jedec_sync(struct mtd_info *mtd) {}; +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + +static struct mtd_info *jedec_probe(struct map_info *map); + + + +static struct mtd_chip_driver jedec_chipdrv = { + .probe = jedec_probe, + .name = "jedec", + .module = THIS_MODULE +}; + +/* Probe entry point */ + +static struct mtd_info *jedec_probe(struct map_info *map) +{ + struct mtd_info *MTD; + struct jedec_private *priv; + unsigned long Base; + unsigned long SectorSize; + unsigned count; + unsigned I,Uniq; + char Part[200]; + memset(&priv,0,sizeof(priv)); + + MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL); + if (!MTD) + return NULL; + + priv = (struct jedec_private *)&MTD[1]; + + my_bank_size = map->size; + + if (map->size/my_bank_size > MAX_JEDEC_CHIPS) + { + printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n"); + kfree(MTD); + return NULL; + } + + for (Base = 0; Base < map->size; Base += my_bank_size) + { + // Perhaps zero could designate all tests? + if (map->buswidth == 0) + map->buswidth = 1; + + if (map->buswidth == 1){ + if (jedec_probe8(map,Base,priv) == 0) { + printk("did recognize jedec chip\n"); + kfree(MTD); + return NULL; + } + } + if (map->buswidth == 2) + jedec_probe16(map,Base,priv); + if (map->buswidth == 4) + jedec_probe32(map,Base,priv); + } + + // Get the biggest sector size + SectorSize = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + // printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec); + // printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize); + if (priv->chips[I].sectorsize > SectorSize) + SectorSize = priv->chips[I].sectorsize; + } + + // Quickly ensure that the other sector sizes are factors of the largest + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize) + { + printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); + kfree(MTD); + return NULL; + } + } + + /* Generate a part name that includes the number of different chips and + other configuration information */ + count = 1; + strlcpy(Part,map->name,sizeof(Part)-10); + strcat(Part," "); + Uniq = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + const struct JEDECTable *JEDEC; + + if (priv->chips[I+1].jedec == priv->chips[I].jedec) + { + count++; + continue; + } + + // Locate the chip in the jedec table + JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec); + if (JEDEC == 0) + { + printk("mtd: Internal Error, JEDEC not set\n"); + kfree(MTD); + return NULL; + } + + if (Uniq != 0) + strcat(Part,","); + Uniq++; + + if (count != 1) + sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); + else + sprintf(Part+strlen(Part),"%s",JEDEC->name); + if (strlen(Part) > sizeof(Part)*2/3) + break; + count = 1; + } + + /* Determine if the chips are organized in a linear fashion, or if there + are empty banks. Note, the last bank does not count here, only the + first banks are important. Holes on non-bank boundaries can not exist + due to the way the detection algorithm works. */ + if (priv->size < my_bank_size) + my_bank_size = priv->size; + priv->is_banked = 0; + //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size); + //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]); + if (!priv->size) { + printk("priv->size is zero\n"); + kfree(MTD); + return NULL; + } + if (priv->size/my_bank_size) { + if (priv->size/my_bank_size == 1) { + priv->size = my_bank_size; + } + else { + for (I = 0; I != priv->size/my_bank_size - 1; I++) + { + if (priv->bank_fill[I] != my_bank_size) + priv->is_banked = 1; + + /* This even could be eliminated, but new de-optimized read/write + functions have to be written */ + printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]); + if (priv->bank_fill[I] != priv->bank_fill[0]) + { + printk("mtd: Failed. Cannot handle unsymmetric banking\n"); + kfree(MTD); + return NULL; + } + } + } + } + if (priv->is_banked == 1) + strcat(Part,", banked"); + + // printk("Part: '%s'\n",Part); + + memset(MTD,0,sizeof(*MTD)); + // strlcpy(MTD->name,Part,sizeof(MTD->name)); + MTD->name = map->name; + MTD->type = MTD_NORFLASH; + MTD->flags = MTD_CAP_NORFLASH; + MTD->writesize = 1; + MTD->erasesize = SectorSize*(map->buswidth); + // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize); + MTD->size = priv->size; + // printk("MTD->size is %x\n",(unsigned int)MTD->size); + //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module? + MTD->erase = flash_erase; + if (priv->is_banked == 1) + MTD->read = jedec_read_banked; + else + MTD->read = jedec_read; + MTD->write = flash_write; + MTD->sync = jedec_sync; + MTD->priv = map; + map->fldrv_priv = priv; + map->fldrv = &jedec_chipdrv; + __module_get(THIS_MODULE); + return MTD; +} + +/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ +static int checkparity(u_char C) +{ + u_char parity = 0; + while (C != 0) + { + parity ^= C & 1; + C >>= 1; + } + + return parity == 1; +} + + +/* Take an array of JEDEC numbers that represent interleved flash chips + and process them. Check to make sure they are good JEDEC numbers, look + them up and then add them to the chip list */ +static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, + unsigned long base,struct jedec_private *priv) +{ + unsigned I,J; + unsigned long Size; + unsigned long SectorSize; + const struct JEDECTable *JEDEC; + + // Test #2 JEDEC numbers exhibit odd parity + for (I = 0; I != Count; I++) + { + if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) + return 0; + } + + // Finally, just make sure all the chip sizes are the same + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + Size = JEDEC->size; + SectorSize = JEDEC->sectorsize; + for (I = 0; I != Count; I++) + { + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize) + { + printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); + return 0; + } + } + + // Load the Chips + for (I = 0; I != MAX_JEDEC_CHIPS; I++) + { + if (priv->chips[I].jedec == 0) + break; + } + + if (I + Count > MAX_JEDEC_CHIPS) + { + printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); + return 0; + } + + // Add them to the table + for (J = 0; J != Count; J++) + { + unsigned long Bank; + + JEDEC = jedec_idtoinf(Mfg[J],Id[J]); + priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; + priv->chips[I].size = JEDEC->size; + priv->chips[I].sectorsize = JEDEC->sectorsize; + priv->chips[I].base = base + J; + priv->chips[I].datashift = J*8; + priv->chips[I].capabilities = JEDEC->capabilities; + priv->chips[I].offset = priv->size + J; + + // log2 n :| + priv->chips[I].addrshift = 0; + for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); + + // Determine how filled this bank is. + Bank = base & (~(my_bank_size-1)); + if (priv->bank_fill[Bank/my_bank_size] < base + + (JEDEC->size << priv->chips[I].addrshift) - Bank) + priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; + I++; + } + + priv->size += priv->chips[I-1].size*Count; + + return priv->chips[I-1].size; +} + +/* Lookup the chip information from the JEDEC ID table. */ +static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) +{ + __u16 Id = (mfr << 8) | id; + unsigned long I = 0; + for (I = 0; JEDEC_table[I].jedec != 0; I++) + if (JEDEC_table[I].jedec == Id) + return JEDEC_table + I; + return NULL; +} + +// Look for flash using an 8 bit bus interface +static int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map_read8(map,base+x) + #define flwrite(v,x) map_write8(map,v,base+x) + + const unsigned long AutoSel1 = 0xAA; + const unsigned long AutoSel2 = 0x55; + const unsigned long AutoSel3 = 0x90; + const unsigned long Reset = 0xF0; + __u32 OldVal; + __u8 Mfg[1]; + __u8 Id[1]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Get the JEDEC numbers + Mfg[0] = flread(0); + Id[0] = flread(1); + // printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]); + + Size = handle_jedecs(map,Mfg,Id,1,base,priv); + // printk("handle_jedecs Size is %x\n",(unsigned int)Size); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + + // Reset. + flwrite(Reset,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +// Look for flash using a 16 bit bus interface (ie 2 8-bit chips) +static int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + return 0; +} + +// Look for flash using a 32 bit bus interface (ie 4 8-bit chips) +static int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map_read32(map,base+((x)<<2)) + #define flwrite(v,x) map_write32(map,v,base+((x)<<2)) + + const unsigned long AutoSel1 = 0xAAAAAAAA; + const unsigned long AutoSel2 = 0x55555555; + const unsigned long AutoSel3 = 0x90909090; + const unsigned long Reset = 0xF0F0F0F0; + __u32 OldVal; + __u8 Mfg[4]; + __u8 Id[4]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 + if (flread(0) != flread(0x100) || + flread(1) != flread(0x101)) + { + flwrite(Reset,0x555); + return 0; + } + + // Split up the JEDEC numbers + OldVal = flread(0); + for (I = 0; I != 4; I++) + Mfg[I] = (OldVal >> (I*8)); + OldVal = flread(1); + for (I = 0; I != 4; I++) + Id[I] = (OldVal >> (I*8)); + + Size = handle_jedecs(map,Mfg,Id,4,base,priv); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + /* Check if there is address wrap around within a single bank, if this + returns JEDEC numbers then we assume that it is wrap around. Notice + we call this routine with the JEDEC return still enabled, if two or + more flashes have a truncated address space the probe test will still + work */ + if (base + (Size<<2)+0x555 < map->size && + base + (Size<<2)+0x555 < (base & (~(my_bank_size-1))) + my_bank_size) + { + if (flread(base+Size) != flread(base+Size + 0x100) || + flread(base+Size + 1) != flread(base+Size + 0x101)) + { + jedec_probe32(map,base+Size,priv); + } + } + + // Reset. + flwrite(0xF0F0F0F0,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +/* Linear read. */ +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + + map_copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +/* Banked read. Take special care to jump past the holes in the bank + mapping. This version assumes symetry in the holes.. */ +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + + *retlen = 0; + while (len > 0) + { + // Determine what bank and offset into that bank the first byte is + unsigned long bank = from & (~(priv->bank_fill[0]-1)); + unsigned long offset = from & (priv->bank_fill[0]-1); + unsigned long get = len; + if (priv->bank_fill[0] - offset < len) + get = priv->bank_fill[0] - offset; + + bank /= priv->bank_fill[0]; + map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); + + len -= get; + *retlen += get; + from += get; + } + return 0; +} + +/* Pass the flags value that the flash return before it re-entered read + mode. */ +static void jedec_flash_failed(unsigned char code) +{ + /* Bit 5 being high indicates that there was an internal device + failure, erasure time limits exceeded or something */ + if ((code & (1 << 5)) != 0) + { + printk("mtd: Internal Flash failure\n"); + return; + } + printk("mtd: Programming didn't take\n"); +} + +/* This uses the erasure function described in the AMD Flash Handbook, + it will work for flashes with a fixed sector size only. Flashes with + a selection of sector sizes (ie the AMD Am29F800B) will need a different + routine. This routine tries to parallize erasing multiple chips/sectors + where possible */ +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + // Does IO to the currently selected chip + #define flread(x) map_read8(map,chip->base+((x)<addrshift)) + #define flwrite(v,x) map_write8(map,v,chip->base+((x)<addrshift)) + + unsigned long Time = 0; + unsigned long NoTime = 0; + unsigned long start = instr->addr, len = instr->len; + unsigned int I; + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + + // Verify the arguments.. + if (start + len > mtd->size || + (start % mtd->erasesize) != 0 || + (len % mtd->erasesize) != 0 || + (len/mtd->erasesize) == 0) + return -EINVAL; + + jedec_flash_chip_scan(priv,start,len); + + // Start the erase sequence on each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + unsigned long off; + struct jedec_flash_chip *chip = priv->chips + I; + + if (chip->length == 0) + continue; + + if (chip->start + chip->length > chip->size) + { + printk("DIE\n"); + return -EIO; + } + + flwrite(0xF0,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + flwrite(0x80,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing + and ignore the other sectors */ + for (off = 0; off < len; off += chip->sectorsize) + { + // Check to make sure we didn't timeout + flwrite(0x30,chip->start + off); + if (off == 0) + continue; + if ((flread(chip->start + off) & (1 << 3)) != 0) + { + printk("mtd: Ack! We timed out the erase timer!\n"); + return -EIO; + } + } + } + + /* We could split this into a timer routine and return early, performing + background erasure.. Maybe later if the need warrents */ + + /* Poll the flash for erasure completion, specs say this can take as long + as 480 seconds to do all the sectors (for a 2 meg flash). + Erasure time is dependent on chip age, temp and wear.. */ + + /* This being a generic routine assumes a 32 bit bus. It does read32s + and bundles interleved chips into the same grouping. This will work + for all bus widths */ + Time = 0; + NoTime = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long off = 0; + unsigned todo[4] = {0,0,0,0}; + unsigned todo_left = 0; + unsigned J; + + if (chip->length == 0) + continue; + + /* Find all chips in this data line, realistically this is all + or nothing up to the interleve count */ + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + { + todo_left++; + todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; + } + } + + /* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], + (short)todo[2],(short)todo[3]); + */ + while (1) + { + __u32 Last[4]; + unsigned long Count = 0; + + /* During erase bit 7 is held low and bit 6 toggles, we watch this, + should it stop toggling or go high then the erase is completed, + or this is not really flash ;> */ + switch (map->buswidth) { + case 1: + Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 3: + Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count = 3; + while (todo_left != 0) + { + for (J = 0; J != 4; J++) + { + __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF; + __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF; + __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; + if (todo[J] == 0) + continue; + + if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) + { +// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); + continue; + } + + if (Byte1 == Byte2) + { + jedec_flash_failed(Byte3); + return -EIO; + } + + todo[J] = 0; + todo_left--; + } + +/* if (NoTime == 0) + Time += HZ/10 - schedule_timeout(HZ/10);*/ + NoTime = 0; + + switch (map->buswidth) { + case 1: + Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 4: + Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count++; + +/* // Count time, max of 15s per sector (according to AMD) + if (Time > 15*len/mtd->erasesize*HZ) + { + printk("mtd: Flash Erase Timed out\n"); + return -EIO; + } */ + } + + // Skip to the next chip if we used chip erase + if (chip->length == chip->size) + off = chip->size; + else + off += chip->sectorsize; + + if (off >= chip->length) + break; + NoTime = 1; + } + + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + priv->chips[J].length = 0; + } + } + + //printk("done\n"); + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; + + #undef flread + #undef flwrite +} + +/* This is the simple flash writing function. It writes to every byte, in + sequence. It takes care of how to properly address the flash if + the flash is interleved. It can only be used if all the chips in the + array are identical!*/ +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + /* Does IO to the currently selected chip. It takes the bank addressing + base (which is divisible by the chip size) adds the necessary lower bits + of addrshift (interleave index) and then adds the control register index. */ + #define flread(x) map_read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) + #define flwrite(v,x) map_write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) + + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + unsigned long base; + unsigned long off; + size_t save_len = len; + + if (start + len > mtd->size) + return -EIO; + + //printk("Here"); + + //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len); + while (len != 0) + { + struct jedec_flash_chip *chip = priv->chips; + unsigned long bank; + unsigned long boffset; + + // Compute the base of the flash. + off = ((unsigned long)start) % (chip->size << chip->addrshift); + base = start - off; + + // Perform banked addressing translation. + bank = base & (~(priv->bank_fill[0]-1)); + boffset = base & (priv->bank_fill[0]-1); + bank = (bank/priv->bank_fill[0])*my_bank_size; + base = bank + boffset; + + // printk("Flasing %X %X %X\n",base,chip->size,len); + // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift); + + // Loop over this page + for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) + { + unsigned char oldbyte = map_read8(map,base+off); + unsigned char Last[4]; + unsigned long Count = 0; + + if (oldbyte == *buf) { + // printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len); + continue; + } + if (((~oldbyte) & *buf) != 0) + printk("mtd: warn: Trying to set a 0 to a 1\n"); + + // Write + flwrite(0xAA,0x555); + flwrite(0x55,0x2AA); + flwrite(0xA0,0x555); + map_write8(map,*buf,base + off); + Last[0] = map_read8(map,base + off); + Last[1] = map_read8(map,base + off); + Last[2] = map_read8(map,base + off); + + /* Wait for the flash to finish the operation. We store the last 4 + status bytes that have been retrieved so we can determine why + it failed. The toggle bits keep toggling when there is a + failure */ + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && + Count < 10000; Count++) + Last[Count % 4] = map_read8(map,base + off); + if (Last[(Count - 1) % 4] != *buf) + { + jedec_flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + } + } + *retlen = save_len; + return 0; +} + +/* This is used to enhance the speed of the erase routine, + when things are being done to multiple chips it is possible to + parallize the operations, particularly full memory erases of multi + chip memories benifit */ +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len) +{ + unsigned int I; + + // Zero the records + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + priv->chips[I].start = priv->chips[I].length = 0; + + // Intersect the region with each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long ByteStart; + unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); + + // End is before this chip or the start is after it + if (start+len < chip->offset || + ChipEndByte - (1 << chip->addrshift) < start) + continue; + + if (start < chip->offset) + { + ByteStart = chip->offset; + chip->start = 0; + } + else + { + chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; + ByteStart = start; + } + + if (start + len >= ChipEndByte) + chip->length = (ChipEndByte - ByteStart) >> chip->addrshift; + else + chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift; + } +} + +int __init jedec_init(void) +{ + register_mtd_chip_driver(&jedec_chipdrv); + return 0; +} + +static void __exit jedec_exit(void) +{ + unregister_mtd_chip_driver(&jedec_chipdrv); +} + +module_init(jedec_init); +module_exit(jedec_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jason Gunthorpe et al."); +MODULE_DESCRIPTION("Old MTD chip driver for JEDEC-compliant flash chips"); diff --git a/trunk/drivers/mtd/chips/sharp.c b/trunk/drivers/mtd/chips/sharp.c new file mode 100644 index 000000000000..c9cd3d21ccfa --- /dev/null +++ b/trunk/drivers/mtd/chips/sharp.c @@ -0,0 +1,601 @@ +/* + * MTD chip driver for pre-CFI Sharp flash chips + * + * Copyright 2000,2001 David A. Schleef + * 2000,2001 Lineo, Inc. + * + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $ + * + * Devices supported: + * LH28F016SCT Symmetrical block flash memory, 2Mx8 + * LH28F008SCT Symmetrical block flash memory, 1Mx8 + * + * Documentation: + * http://www.sharpmeg.com/datasheets/memic/flashcmp/ + * http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf + * 016sctl9.pdf + * + * Limitations: + * This driver only supports 4x1 arrangement of chips. + * Not tested on anything but PowerPC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_RESET 0xffffffff +#define CMD_READ_ID 0x90909090 +#define CMD_READ_STATUS 0x70707070 +#define CMD_CLEAR_STATUS 0x50505050 +#define CMD_BLOCK_ERASE_1 0x20202020 +#define CMD_BLOCK_ERASE_2 0xd0d0d0d0 +#define CMD_BYTE_WRITE 0x40404040 +#define CMD_SUSPEND 0xb0b0b0b0 +#define CMD_RESUME 0xd0d0d0d0 +#define CMD_SET_BLOCK_LOCK_1 0x60606060 +#define CMD_SET_BLOCK_LOCK_2 0x01010101 +#define CMD_SET_MASTER_LOCK_1 0x60606060 +#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1 +#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060 +#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0 + +#define SR_READY 0x80808080 // 1 = ready +#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended +#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits +#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit +#define SR_VPP 0x08080808 // 1 = Vpp is low +#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended +#define SR_PROTECT 0x02020202 // 1 = lock bit set +#define SR_RESERVED 0x01010101 + +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT) + +/* Configuration options */ + +#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ + +static struct mtd_info *sharp_probe(struct map_info *); + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, const u_char *buf); +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr); +static void sharp_sync(struct mtd_info *mtd); +static int sharp_suspend(struct mtd_info *mtd); +static void sharp_resume(struct mtd_info *mtd); +static void sharp_destroy(struct mtd_info *mtd); + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum); +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#endif + + +struct sharp_info{ + struct flchip *chip; + int bogus; + int chipshift; + int numchips; + struct flchip chips[1]; +}; + +static void sharp_destroy(struct mtd_info *mtd); + +static struct mtd_chip_driver sharp_chipdrv = { + .probe = sharp_probe, + .destroy = sharp_destroy, + .name = "sharp", + .module = THIS_MODULE +}; + + +static struct mtd_info *sharp_probe(struct map_info *map) +{ + struct mtd_info *mtd = NULL; + struct sharp_info *sharp = NULL; + int width; + + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); + if(!mtd) + return NULL; + + sharp = kzalloc(sizeof(*sharp), GFP_KERNEL); + if(!sharp) { + kfree(mtd); + return NULL; + } + + width = sharp_probe_map(map,mtd); + if(!width){ + kfree(mtd); + kfree(sharp); + return NULL; + } + + mtd->priv = map; + mtd->type = MTD_NORFLASH; + mtd->erase = sharp_erase; + mtd->read = sharp_read; + mtd->write = sharp_write; + mtd->sync = sharp_sync; + mtd->suspend = sharp_suspend; + mtd->resume = sharp_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->writesize = 1; + mtd->name = map->name; + + sharp->chipshift = 23; + sharp->numchips = 1; + sharp->chips[0].start = 0; + sharp->chips[0].state = FL_READY; + sharp->chips[0].mutex = &sharp->chips[0]._spinlock; + sharp->chips[0].word_write_time = 0; + init_waitqueue_head(&sharp->chips[0].wq); + spin_lock_init(&sharp->chips[0]._spinlock); + + map->fldrv = &sharp_chipdrv; + map->fldrv_priv = sharp; + + __module_get(THIS_MODULE); + return mtd; +} + +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr) +{ + map_word map_cmd; + map_cmd.x[0] = cmd; + map_write(map, map_cmd, adr); +} + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) +{ + map_word tmp, read0, read4; + unsigned long base = 0; + int width = 4; + + tmp = map_read(map, base+0); + + sharp_send_cmd(map, CMD_READ_ID, base+0); + + read0 = map_read(map, base+0); + read4 = map_read(map, base+4); + if(read0.x[0] == 0x89898989){ + printk("Looks like sharp flash\n"); + switch(read4.x[0]){ + case 0xaaaaaaaa: + case 0xa0a0a0a0: + /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/ + /* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x200000 * width; + return width; + case 0xa6a6a6a6: + /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/ + /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x100000 * width; + return width; +#if 0 + case 0x00000000: /* unknown */ + /* XX - LH28F004SCT 512kx8, 8 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x80000 * width; + return width; +#endif + default: + printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); + } + }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){ + /* RAM, probably */ + printk("Looks like RAM\n"); + map_write(map, tmp, base+0); + }else{ + printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); + } + + return 0; +} + +/* This function returns with the chip->mutex lock held. */ +static int sharp_wait(struct map_info *map, struct flchip *chip) +{ + int i; + map_word status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + int adr = 0; + +retry: + spin_lock_bh(chip->mutex); + + switch(chip->state){ + case FL_READY: + sharp_send_cmd(map, CMD_READ_STATUS, adr); + chip->state = FL_STATUS; + case FL_STATUS: + for(i=0;i<100;i++){ + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY) + break; + udelay(1); + } + break; + default: + printk("Waiting for chip\n"); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + sharp_send_cmd(map, CMD_RESET, adr); + + chip->state = FL_READY; + + return 0; +} + +static void sharp_release(struct flchip *chip) +{ + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); +} + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int chipnum; + int ret = 0; + int ofs = 0; + + chipnum = (from >> sharp->chipshift); + ofs = from & ((1 << sharp->chipshift)-1); + + *retlen = 0; + + while(len){ + unsigned long thislen; + + if(chipnum>=sharp->numchips) + break; + + thislen = len; + if(ofs+thislen >= (1<chipshift)) + thislen = (1<chipshift) - ofs; + + ret = sharp_wait(map,&sharp->chips[chipnum]); + if(ret<0) + break; + + map_copy_from(map,buf,ofs,thislen); + + sharp_release(&sharp->chips[chipnum]); + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int ret = 0; + int i,j; + int chipnum; + unsigned long ofs; + union { u32 l; unsigned char uc[4]; } tbuf; + + *retlen = 0; + + while(len){ + tbuf.l = 0xffffffff; + chipnum = to >> sharp->chipshift; + ofs = to & ((1<chipshift)-1); + + j=0; + for(i=ofs&3;i<4 && len;i++){ + tbuf.uc[i] = *buf; + buf++; + to++; + len--; + j++; + } + sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l); + if(ret<0) + return ret; + (*retlen)+=j; + } + + return 0; +} + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + int ret; + int timeo; + int try; + int i; + map_word data, status; + + status.x[0] = 0; + ret = sharp_wait(map,chip); + + for(try=0;try<10;try++){ + sharp_send_cmd(map, CMD_BYTE_WRITE, adr); + /* cpu_to_le32 -> hack to fix the writel be->le conversion */ + data.x[0] = cpu_to_le32(datum); + map_write(map, data, adr); + + chip->state = FL_WRITING; + + timeo = jiffies + (HZ/2); + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + for(i=0;i<100;i++){ + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) + break; + } + if(i==100){ + printk("sharp: timed out writing\n"); + } + + if(!(status.x[0] & SR_ERRORS)) + break; + + printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]); + + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); + } + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + unsigned long adr,len; + int chipnum, ret=0; + +//printk("sharp_erase()\n"); + if(instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len + instr->addr > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> sharp->chipshift; + adr = instr->addr & ((1<chipshift)-1); + len = instr->len; + + while(len){ + ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr); + if(ret)return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + if(adr >> sharp->chipshift){ + adr = 0; + chipnum++; + if(chipnum>=sharp->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + unsigned long timeo; + map_word status; + DECLARE_WAITQUEUE(wait, current); + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + + timeo = jiffies + HZ; + + while(time_before(jiffies, timeo)){ + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY){ + ret = 0; + goto out; + } + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + //spin_unlock_bh(chip->mutex); + + schedule_timeout(1); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + //spin_lock_bh(chip->mutex); + + if (signal_pending(current)){ + ret = -EINTR; + goto out; + } + + } + ret = -ETIME; +out: + return ret; +} + +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + //int timeo; + map_word status; + //int i; + +//printk("sharp_erase_oneblock()\n"); + +#ifdef AUTOUNLOCK + /* This seems like a good place to do an unlock */ + sharp_unlock_oneblock(map,chip,adr); +#endif + + sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr); + sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr); + + chip->state = FL_ERASING; + + ret = sharp_do_wait_for_ready(map,chip,adr); + if(ret<0)return ret; + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + //spin_unlock_bh(chip->mutex); + return 0; + } + + printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); + + //spin_unlock_bh(chip->mutex); + + return -EIO; +} + +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int i; + map_word status; + + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr); + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr); + + udelay(100); + + status = map_read(map, adr); + printk("status=%08lx\n", status.x[0]); + + for(i=0;i<1000;i++){ + //sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) + break; + udelay(100); + } + if(i==1000){ + printk("sharp: timed out unlocking block\n"); + } + + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + return; + } + + printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); +} +#endif + +static void sharp_sync(struct mtd_info *mtd) +{ + //printk("sharp_sync()\n"); +} + +static int sharp_suspend(struct mtd_info *mtd) +{ + printk("sharp_suspend()\n"); + return -EINVAL; +} + +static void sharp_resume(struct mtd_info *mtd) +{ + printk("sharp_resume()\n"); + +} + +static void sharp_destroy(struct mtd_info *mtd) +{ + printk("sharp_destroy()\n"); + +} + +static int __init sharp_probe_init(void) +{ + printk("MTD Sharp chip driver \n"); + + register_mtd_chip_driver(&sharp_chipdrv); + + return 0; +} + +static void __exit sharp_probe_exit(void) +{ + unregister_mtd_chip_driver(&sharp_chipdrv); +} + +module_init(sharp_probe_init); +module_exit(sharp_probe_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Schleef "); +MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips"); diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c index be4b9948c762..fc4cc8ba9e29 100644 --- a/trunk/drivers/mtd/devices/block2mtd.c +++ b/trunk/drivers/mtd/devices/block2mtd.c @@ -373,7 +373,7 @@ static inline void kill_final_newline(char *str) #ifndef MODULE static int block2mtd_init_called = 0; -static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ +static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ #endif diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index b665e4ac2208..d990d8141ef5 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -60,7 +60,7 @@ config MTD_PHYSMAP_BANKWIDTH (i.e., run-time calling physmap_configure()). config MTD_PHYSMAP_OF - tristate "Flash device in physical memory map based on OF description" + tristate "Flash device in physical memory map based on OF descirption" depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM) help This provides a 'mapping' driver which allows the NOR Flash and @@ -358,6 +358,22 @@ config MTD_CFI_FLAGADM Mapping for the Flaga digital module. If you don't have one, ignore this setting. +config MTD_BEECH + tristate "CFI Flash device mapped on IBM 405LP Beech" + depends on MTD_CFI && BEECH + help + This enables access routines for the flash chips on the IBM + 405LP Beech board. If you have one of these boards and would like + to use the flash chips on it, say 'Y'. + +config MTD_ARCTIC + tristate "CFI Flash device mapped on IBM 405LP Arctic" + depends on MTD_CFI && ARCTIC2 + help + This enables access routines for the flash chips on the IBM 405LP + Arctic board. If you have one of these boards and would like to + use the flash chips on it, say 'Y'. + config MTD_WALNUT tristate "Flash device mapped on IBM 405GP Walnut" depends on MTD_JEDECPROBE && WALNUT diff --git a/trunk/drivers/mtd/maps/Makefile b/trunk/drivers/mtd/maps/Makefile index 3acbb5d01ca4..de036c5e6139 100644 --- a/trunk/drivers/mtd/maps/Makefile +++ b/trunk/drivers/mtd/maps/Makefile @@ -58,6 +58,8 @@ obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o obj-$(CONFIG_MTD_EBONY) += ebony.o obj-$(CONFIG_MTD_OCOTEA) += ocotea.o +obj-$(CONFIG_MTD_BEECH) += beech-mtd.o +obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o obj-$(CONFIG_MTD_WALNUT) += walnut.o obj-$(CONFIG_MTD_H720X) += h720x-flash.o obj-$(CONFIG_MTD_SBC8240) += sbc8240.o diff --git a/trunk/drivers/mtd/maps/arctic-mtd.c b/trunk/drivers/mtd/maps/arctic-mtd.c new file mode 100644 index 000000000000..2cc902436275 --- /dev/null +++ b/trunk/drivers/mtd/maps/arctic-mtd.c @@ -0,0 +1,145 @@ +/* + * $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for + * IBM 405LP Arctic boards. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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) 2002, International Business Machines Corporation + * All Rights Reserved. + * + * Bishop Brock + * IBM Research, Austin Center for Low-Power Computing + * bcbrock@us.ibm.com + * March 2002 + * + * modified for Arctic by, + * David Gibson + * IBM OzLabs, Canberra, Australia + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* + * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB) + * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB) + * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP) + * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB) + */ + +#define FFS1_SIZE 0x01000000 /* 16MiB */ +#define KERNEL_SIZE 0x00500000 /* 5.12MiB */ +#define FFS2_SIZE 0x00a60000 /* 10.624MiB */ +#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */ + + +#define NAME "Arctic Linux Flash" +#define PADDR SUBZERO_BOOTFLASH_PADDR +#define BUSWIDTH 2 +#define SIZE SUBZERO_BOOTFLASH_SIZE +#define PARTITIONS 4 + +/* Flash memories on these boards are memory resources, accessed big-endian. */ + +{ + /* do nothing for now */ +} + +static struct map_info arctic_mtd_map = { + .name = NAME, + .size = SIZE, + .bankwidth = BUSWIDTH, + .phys = PADDR, +}; + +static struct mtd_info *arctic_mtd; + +static struct mtd_partition arctic_partitions[PARTITIONS] = { + { .name = "Filesystem", + .size = FFS1_SIZE, + .offset = 0,}, + { .name = "Kernel", + .size = KERNEL_SIZE, + .offset = FFS1_SIZE,}, + { .name = "Filesystem", + .size = FFS2_SIZE, + .offset = FFS1_SIZE + KERNEL_SIZE,}, + { .name = "Firmware", + .size = FIRMWARE_SIZE, + .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,}, +}; + +static int __init +init_arctic_mtd(void) +{ + int err; + + printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); + + arctic_mtd_map.virt = ioremap(PADDR, SIZE); + + if (!arctic_mtd_map.virt) { + printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); + return -EIO; + } + simple_map_init(&arctic_mtd_map); + + 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(arctic_mtd_map.virt); + 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(arctic_mtd_map.virt); + } + + return err; +} + +static void __exit +cleanup_arctic_mtd(void) +{ + if (arctic_mtd) { + del_mtd_partitions(arctic_mtd); + map_destroy(arctic_mtd); + iounmap((void *) arctic_mtd_map.virt); + } +} + +module_init(init_arctic_mtd); +module_exit(cleanup_arctic_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Gibson "); +MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards"); diff --git a/trunk/drivers/mtd/maps/beech-mtd.c b/trunk/drivers/mtd/maps/beech-mtd.c new file mode 100644 index 000000000000..d76d5981b863 --- /dev/null +++ b/trunk/drivers/mtd/maps/beech-mtd.c @@ -0,0 +1,122 @@ +/* + * $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for + * IBM 405LP Beech boards. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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) 2002, International Business Machines Corporation + * All Rights Reserved. + * + * Bishop Brock + * IBM Research, Austin Center for Low-Power Computing + * bcbrock@us.ibm.com + * March 2002 + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define NAME "Beech Linux Flash" +#define PADDR BEECH_BIGFLASH_PADDR +#define SIZE BEECH_BIGFLASH_SIZE +#define BUSWIDTH 1 + +/* Flash memories on these boards are memory resources, accessed big-endian. */ + + +static struct map_info beech_mtd_map = { + .name = NAME, + .size = SIZE, + .bankwidth = BUSWIDTH, + .phys = PADDR +}; + +static struct mtd_info *beech_mtd; + +static struct mtd_partition beech_partitions[2] = { + { + .name = "Linux Kernel", + .size = BEECH_KERNEL_SIZE, + .offset = BEECH_KERNEL_OFFSET + }, { + .name = "Free Area", + .size = BEECH_FREE_AREA_SIZE, + .offset = BEECH_FREE_AREA_OFFSET + } +}; + +static int __init +init_beech_mtd(void) +{ + int err; + + printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); + + beech_mtd_map.virt = ioremap(PADDR, SIZE); + + if (!beech_mtd_map.virt) { + printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); + return -EIO; + } + + simple_map_init(&beech_mtd_map); + + 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(beech_mtd_map.virt); + 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(beech_mtd_map.virt); + } + + return err; +} + +static void __exit +cleanup_beech_mtd(void) +{ + if (beech_mtd) { + del_mtd_partitions(beech_mtd); + map_destroy(beech_mtd); + iounmap((void *) beech_mtd_map.virt); + } +} + +module_init(init_beech_mtd); +module_exit(cleanup_beech_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bishop Brock "); +MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards"); diff --git a/trunk/drivers/mtd/maps/nettel.c b/trunk/drivers/mtd/maps/nettel.c index 7b96cd02f82b..9f53c655af3a 100644 --- a/trunk/drivers/mtd/maps/nettel.c +++ b/trunk/drivers/mtd/maps/nettel.c @@ -358,7 +358,7 @@ int __init nettel_init(void) /* Turn other PAR off so the first probe doesn't find it */ *intel1par = 0; - /* Probe for the size of the first Intel flash */ + /* Probe for the the size of the first Intel flash */ nettel_intel_map.size = maxsize; nettel_intel_map.phys = intel0addr; nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); diff --git a/trunk/drivers/mtd/maps/physmap_of.c b/trunk/drivers/mtd/maps/physmap_of.c index bbb42c35b69b..72107dc06d67 100644 --- a/trunk/drivers/mtd/maps/physmap_of.c +++ b/trunk/drivers/mtd/maps/physmap_of.c @@ -186,7 +186,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev else { if (strcmp(of_probe, "ROM")) dev_dbg(&dev->dev, "map_probe: don't know probe type " - "'%s', mapping as rom\n", of_probe); + "'%s', mapping as rom\n"); info->mtd = do_map_probe("mtd_rom", &info->map); } if (info->mtd == NULL) { diff --git a/trunk/drivers/mtd/mtdpart.c b/trunk/drivers/mtd/mtdpart.c index 9c6236852942..1af989023c66 100644 --- a/trunk/drivers/mtd/mtdpart.c +++ b/trunk/drivers/mtd/mtdpart.c @@ -347,6 +347,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.name = parts[i].name; + slave->mtd.bank_size = master->bank_size; slave->mtd.owner = master->owner; slave->mtd.read = part_read; diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index f1d60b6f048e..d05873b8c155 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -232,13 +232,11 @@ config MTD_NAND_BASLER_EXCITE will be named "excite_nandflash.ko". config MTD_NAND_CAFE - tristate "NAND support for OLPC CAFÉ chip" - depends on PCI - select REED_SOLOMON - select REED_SOLOMON_DEC16 - help - Use NAND flash attached to the CAFÉ chip designed for the $100 - laptop. + tristate "NAND support for OLPC CAFÉ chip" + depends on PCI + help + Use NAND flash attached to the CAFÉ chip designed for the $100 + laptop. config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" @@ -272,13 +270,4 @@ config MTD_NAND_NANDSIM The simulator may simulate various NAND flash chips for the MTD nand layer. -config MTD_NAND_PLATFORM - tristate "Support for generic platform NAND driver" - depends on MTD_NAND - help - This implements a generic NAND driver for on-SOC platform - devices. You will need to provide platform-specific functions - via platform_data. - - endif # MTD_NAND diff --git a/trunk/drivers/mtd/nand/Makefile b/trunk/drivers/mtd/nand/Makefile index edba1db14bfa..6872031a3fb2 100644 --- a/trunk/drivers/mtd/nand/Makefile +++ b/trunk/drivers/mtd/nand/Makefile @@ -26,6 +26,6 @@ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o -obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o nand-objs := nand_base.o nand_bbt.o +cafe_nand-objs := cafe.o cafe_ecc.o diff --git a/trunk/drivers/mtd/nand/at91_nand.c b/trunk/drivers/mtd/nand/at91_nand.c index 512e999177f7..14b80cc90a7b 100644 --- a/trunk/drivers/mtd/nand/at91_nand.c +++ b/trunk/drivers/mtd/nand/at91_nand.c @@ -82,10 +82,6 @@ static void at91_nand_disable(struct at91_nand_host *host) at91_set_gpio_value(host->board->enable_pin, 1); } -#ifdef CONFIG_MTD_PARTITIONS -const char *part_probes[] = { "cmdlinepart", NULL }; -#endif - /* * Probe for the NAND device. */ @@ -155,12 +151,6 @@ static int __init at91_nand_probe(struct platform_device *pdev) #ifdef CONFIG_MTD_PARTITIONS if (host->board->partition_info) partitions = host->board->partition_info(mtd->size, &num_partitions); -#ifdef CONFIG_MTD_CMDLINE_PARTS - else { - mtd->name = "at91_nand"; - num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0); - } -#endif if ((!partitions) || (num_partitions == 0)) { printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); diff --git a/trunk/drivers/mtd/nand/cafe_nand.c b/trunk/drivers/mtd/nand/cafe.c similarity index 88% rename from trunk/drivers/mtd/nand/cafe_nand.c rename to trunk/drivers/mtd/nand/cafe.c index cff969d05d4a..c328a7514510 100644 --- a/trunk/drivers/mtd/nand/cafe_nand.c +++ b/trunk/drivers/mtd/nand/cafe.c @@ -11,7 +11,6 @@ #undef DEBUG #include #include -#include #include #include #include @@ -47,14 +46,13 @@ #define CAFE_GLOBAL_IRQ_MASK 0x300c #define CAFE_NAND_RESET 0x3034 -/* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */ -#define CTRL1_CHIPSELECT (1<<19) +int cafe_correct_ecc(unsigned char *buf, + unsigned short *chk_syndrome_list); struct cafe_priv { struct nand_chip nand; struct pci_dev *pdev; void __iomem *mmio; - struct rs_control *rs; uint32_t ctl1; uint32_t ctl2; int datalen; @@ -197,8 +195,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, cafe->data_pos = cafe->datalen = 0; - /* Set command valid bit, mask in the chip select bit */ - ctl1 = 0x80000000 | command | (cafe->ctl1 & CTRL1_CHIPSELECT); + /* Set command valid bit */ + ctl1 = 0x80000000 | command; /* Set RD or WR bits as appropriate */ if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) { @@ -311,16 +309,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, static void cafe_select_chip(struct mtd_info *mtd, int chipnr) { - struct cafe_priv *cafe = mtd->priv; - - cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); - - /* Mask the appropriate bit into the stored value of ctl1 - which will be used by cafe_nand_cmdfunc() */ - if (chipnr) - cafe->ctl1 |= CTRL1_CHIPSELECT; - else - cafe->ctl1 &= ~CTRL1_CHIPSELECT; + //struct cafe_priv *cafe = mtd->priv; + // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); } static int cafe_nand_interrupt(int irq, void *id) @@ -384,66 +374,28 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { - unsigned short syn[8], pat[4]; - int pos[4]; - u8 *oob = chip->oob_poi; - int i, n; + unsigned short syn[8]; + int i; for (i=0; i<8; i+=2) { uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2)); - syn[i] = cafe->rs->index_of[tmp & 0xfff]; - syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff]; - } - - n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0, - pat); - - for (i = 0; i < n; i++) { - int p = pos[i]; - - /* The 12-bit symbols are mapped to bytes here */ - - if (p > 1374) { - /* out of range */ - n = -1374; - } else if (p == 0) { - /* high four bits do not correspond to data */ - if (pat[i] > 0xff) - n = -2048; - else - buf[0] ^= pat[i]; - } else if (p == 1365) { - buf[2047] ^= pat[i] >> 4; - oob[0] ^= pat[i] << 4; - } else if (p > 1365) { - if ((p & 1) == 1) { - oob[3*p/2 - 2048] ^= pat[i] >> 4; - oob[3*p/2 - 2047] ^= pat[i] << 4; - } else { - oob[3*p/2 - 2049] ^= pat[i] >> 8; - oob[3*p/2 - 2048] ^= pat[i]; - } - } else if ((p & 1) == 1) { - buf[3*p/2] ^= pat[i] >> 4; - buf[3*p/2 + 1] ^= pat[i] << 4; - } else { - buf[3*p/2 - 1] ^= pat[i] >> 8; - buf[3*p/2] ^= pat[i]; - } + syn[i] = tmp & 0xfff; + syn[i+1] = (tmp >> 16) & 0xfff; } - if (n < 0) { + if ((i = cafe_correct_ecc(buf, syn)) < 0) { dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n", cafe_readl(cafe, NAND_ADDR2) * 2048); - for (i = 0; i < 0x5c; i += 4) + for (i=0; i< 0x5c; i+=4) printk("Register %x: %08x\n", i, readl(cafe->mmio + i)); mtd->ecc_stats.failed++; } else { - dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); - mtd->ecc_stats.corrected += n; + dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i); + mtd->ecc_stats.corrected += i; } } + return 0; } @@ -464,7 +416,7 @@ static uint8_t cafe_mirror_pattern_512[] = { 0xBC }; static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 4, .veroffs = 18, @@ -474,7 +426,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 4, .veroffs = 18, @@ -490,7 +442,7 @@ static struct nand_ecclayout cafe_oobinfo_512 = { static struct nand_bbt_descr cafe_bbt_main_descr_512 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 1, .veroffs = 15, @@ -500,7 +452,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_512 = { static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 1, .veroffs = 15, @@ -573,48 +525,6 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) return 0; } -/* F_2[X]/(X**6+X+1) */ -static unsigned short __devinit gf64_mul(u8 a, u8 b) -{ - u8 c; - unsigned int i; - - c = 0; - for (i = 0; i < 6; i++) { - if (a & 1) - c ^= b; - a >>= 1; - b <<= 1; - if ((b & 0x40) != 0) - b ^= 0x43; - } - - return c; -} - -/* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ -static u16 __devinit gf4096_mul(u16 a, u16 b) -{ - u8 ah, al, bh, bl, ch, cl; - - ah = a >> 6; - al = a & 0x3f; - bh = b >> 6; - bl = b & 0x3f; - - ch = gf64_mul(ah ^ al, bh ^ bl) ^ gf64_mul(al, bl); - cl = gf64_mul(gf64_mul(ah, bh), 0x21) ^ gf64_mul(al, bl); - - return (ch << 6) ^ cl; -} - -static int __devinit cafe_mul(int x) -{ - if (x == 0) - return 1; - return gf4096_mul(x, 0xe01); -} - static int __devinit cafe_nand_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -654,12 +564,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, } cafe->nand.buffers = (void *)cafe->dmabuf + 2112; - cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); - if (!cafe->rs) { - err = -ENOMEM; - goto out_ior; - } - cafe->nand.cmdfunc = cafe_nand_cmdfunc; cafe->nand.dev_ready = cafe_device_ready; cafe->nand.read_byte = cafe_read_byte; @@ -742,7 +646,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); /* Scan to find existence of the device */ - if (nand_scan_ident(mtd, 2)) { + if (nand_scan_ident(mtd, 1)) { err = -ENXIO; goto out_irq; } @@ -809,7 +713,6 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev) cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); free_irq(pdev->irq, mtd); nand_release(mtd); - free_rs(cafe->rs); pci_iounmap(pdev, cafe->mmio); dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); kfree(mtd); diff --git a/trunk/drivers/mtd/nand/cafe_ecc.c b/trunk/drivers/mtd/nand/cafe_ecc.c new file mode 100644 index 000000000000..ea5c8491d2c5 --- /dev/null +++ b/trunk/drivers/mtd/nand/cafe_ecc.c @@ -0,0 +1,1381 @@ +/* Error correction for CAFÉ NAND controller + * + * © 2006 Marvell, Inc. + * Author: Tom Chiou + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the 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 + +static unsigned short gf4096_mul(unsigned short, unsigned short); +static unsigned short gf64_mul(unsigned short, unsigned short); +static unsigned short gf4096_inv(unsigned short); +static unsigned short err_pos(unsigned short); +static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short *); +static void zero_4x5_col3(unsigned short[4][5]); +static void zero_4x5_col2(unsigned short[4][5]); +static void zero_4x5_col1(unsigned short[4][5]); +static void swap_4x5_rows(unsigned short[4][5], int, int, int); +static void swap_2x3_rows(unsigned short m[2][3]); +static void solve_4x5(unsigned short m[4][5], unsigned short *, int *); +static void sort_coefs(int *, unsigned short *, int); +static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short *); +static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); +static void zero_3x4_col2(unsigned short[3][4]); +static void zero_3x4_col1(unsigned short[3][4]); +static void swap_3x4_rows(unsigned short[3][4], int, int, int); +static void solve_3x4(unsigned short[3][4], unsigned short *, int *); +static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); + +static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short *); +static void find_2x2_soln(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); +static void solve_2x3(unsigned short[2][3], unsigned short *); +static int chk_no_err_only(unsigned short *, unsigned short *); +static int chk_1_err_only(unsigned short *, unsigned short *); +static int chk_2_err_only(unsigned short *, unsigned short *); +static int chk_3_err_only(unsigned short *, unsigned short *); +static int chk_4_err_only(unsigned short *, unsigned short *); + +static unsigned short gf64_mul(unsigned short a, unsigned short b) +{ + unsigned short tmp1, tmp2, tmp3, tmp4, tmp5; + unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c; + + tmp1 = ((a) ^ (a >> 5)); + tmp2 = ((a >> 4) ^ (a >> 5)); + tmp3 = ((a >> 3) ^ (a >> 4)); + tmp4 = ((a >> 2) ^ (a >> 3)); + tmp5 = ((a >> 1) ^ (a >> 2)); + + c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^ + ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1; + + c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^ + (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1; + + c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^ + (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1; + + c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^ + (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1; + + c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^ + ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1; + + c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^ + ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1; + + c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5); + + return c; +} + +static unsigned short gf4096_mul(unsigned short a, unsigned short b) +{ + unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c; + + ah = (a >> 6) & 0x3f; + al = a & 0x3f; + bh = (b >> 6) & 0x3f; + bl = b & 0x3f; + alxah = al ^ ah; + blxbh = bl ^ bh; + + ablh = gf64_mul(alxah, blxbh); + albl = gf64_mul(al, bl); + ahbh = gf64_mul(ah, bh); + + ahbhB = ((ahbh & 0x1) << 5) | + ((ahbh & 0x20) >> 1) | + ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1); + + c = ((ablh ^ albl) << 6) | (ahbhB ^ albl); + return c; +} + +static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats) +{ + find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats); +} + +static void find_3bit_err_coefs(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs) +{ + unsigned short m[3][4]; + int row_order[3]; + + row_order[0] = 0; + row_order[1] = 1; + row_order[2] = 2; + m[0][0] = s2; + m[0][1] = s1; + m[0][2] = s0; + m[0][3] = s3; + m[1][0] = s3; + m[1][1] = s2; + m[1][2] = s1; + m[1][3] = s4; + m[2][0] = s4; + m[2][1] = s3; + m[2][2] = s2; + m[2][3] = s5; + + if (m[0][2] != 0x0) { + zero_3x4_col2(m); + } else if (m[1][2] != 0x0) { + swap_3x4_rows(m, 0, 1, 4); + zero_3x4_col2(m); + } else if (m[2][2] != 0x0) { + swap_3x4_rows(m, 0, 2, 4); + zero_3x4_col2(m); + } else { + printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n"); + } + + if (m[1][1] != 0x0) { + zero_3x4_col1(m); + } else if (m[2][1] != 0x0) { + swap_3x4_rows(m, 1, 2, 4); + zero_3x4_col1(m); + } else { + printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n"); + } + + /* solve coefs */ + solve_3x4(m, coefs, row_order); +} + +static void zero_3x4_col2(unsigned short m[3][4]) +{ + unsigned short minv1, minv2; + + minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2])); + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2])); + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); + m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1); + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); + m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2); +} + +static void zero_3x4_col1(unsigned short m[3][4]) +{ + unsigned short minv; + minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1])); + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv); + m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv); +} + +static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width) +{ + unsigned short tmp0; + int cnt; + for (cnt = 0; cnt < col_width; cnt++) { + tmp0 = m[i][cnt]; + m[i][cnt] = m[j][cnt]; + m[j][cnt] = tmp0; + } +} + +static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order) +{ + unsigned short tmp[3]; + tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0])); + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1])); + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2])); + sort_coefs(row_order, tmp, 3); + coefs[0] = tmp[0]; + coefs[1] = tmp[1]; + coefs[2] = tmp[2]; +} + +static void find_3bit_err_pats(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short r0, + unsigned short r1, unsigned short r2, + unsigned short *pats) +{ + find_2x2_soln(r0 ^ r2, r1 ^ r2, + gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2), + gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats); + pats[2] = s0 ^ pats[0] ^ pats[1]; +} + +static void find_4bit_err_coefs(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, + unsigned short s4, unsigned short s5, + unsigned short s6, unsigned short s7, + unsigned short *coefs) +{ + unsigned short m[4][5]; + int row_order[4]; + + row_order[0] = 0; + row_order[1] = 1; + row_order[2] = 2; + row_order[3] = 3; + + m[0][0] = s3; + m[0][1] = s2; + m[0][2] = s1; + m[0][3] = s0; + m[0][4] = s4; + m[1][0] = s4; + m[1][1] = s3; + m[1][2] = s2; + m[1][3] = s1; + m[1][4] = s5; + m[2][0] = s5; + m[2][1] = s4; + m[2][2] = s3; + m[2][3] = s2; + m[2][4] = s6; + m[3][0] = s6; + m[3][1] = s5; + m[3][2] = s4; + m[3][3] = s3; + m[3][4] = s7; + + if (m[0][3] != 0x0) { + zero_4x5_col3(m); + } else if (m[1][3] != 0x0) { + swap_4x5_rows(m, 0, 1, 5); + zero_4x5_col3(m); + } else if (m[2][3] != 0x0) { + swap_4x5_rows(m, 0, 2, 5); + zero_4x5_col3(m); + } else if (m[3][3] != 0x0) { + swap_4x5_rows(m, 0, 3, 5); + zero_4x5_col3(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n"); + } + + if (m[1][2] != 0x0) { + zero_4x5_col2(m); + } else if (m[2][2] != 0x0) { + swap_4x5_rows(m, 1, 2, 5); + zero_4x5_col2(m); + } else if (m[3][2] != 0x0) { + swap_4x5_rows(m, 1, 3, 5); + zero_4x5_col2(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n"); + } + + if (m[2][1] != 0x0) { + zero_4x5_col1(m); + } else if (m[3][1] != 0x0) { + swap_4x5_rows(m, 2, 3, 5); + zero_4x5_col1(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n"); + } + + solve_4x5(m, coefs, row_order); +} + +static void zero_4x5_col3(unsigned short m[4][5]) +{ + unsigned short minv1, minv2, minv3; + + minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3])); + minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3])); + minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3])); + + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1); + m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1); + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); + m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2); + m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2); + m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3); + m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3); + m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3); + m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3); +} + +static void zero_4x5_col2(unsigned short m[4][5]) +{ + unsigned short minv2, minv3; + + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2])); + minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2])); + + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2); + m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2); + m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3); + m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3); + m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3); +} + +static void zero_4x5_col1(unsigned short m[4][5]) +{ + unsigned short minv; + + minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1])); + + m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv); + m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv); +} + +static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width) +{ + unsigned short tmp0; + int cnt; + + for (cnt = 0; cnt < col_width; cnt++) { + tmp0 = m[i][cnt]; + m[i][cnt] = m[j][cnt]; + m[j][cnt] = tmp0; + } +} + +static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order) +{ + unsigned short tmp[4]; + + tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0])); + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1])); + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2])); + tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ + gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3])); + sort_coefs(row_order, tmp, 4); + coefs[0] = tmp[0]; + coefs[1] = tmp[1]; + coefs[2] = tmp[2]; + coefs[3] = tmp[3]; +} + +static void sort_coefs(int *order, unsigned short *soln, int len) +{ + int cnt, start_cnt, least_ord, least_cnt; + unsigned short tmp0; + for (start_cnt = 0; start_cnt < len; start_cnt++) { + for (cnt = start_cnt; cnt < len; cnt++) { + if (cnt == start_cnt) { + least_ord = order[cnt]; + least_cnt = start_cnt; + } else { + if (least_ord > order[cnt]) { + least_ord = order[cnt]; + least_cnt = cnt; + } + } + } + if (least_cnt != start_cnt) { + tmp0 = order[least_cnt]; + order[least_cnt] = order[start_cnt]; + order[start_cnt] = tmp0; + tmp0 = soln[least_cnt]; + soln[least_cnt] = soln[start_cnt]; + soln[start_cnt] = tmp0; + } + } +} + +static void find_4bit_err_pats(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, + unsigned short z1, unsigned short z2, + unsigned short z3, unsigned short z4, + unsigned short *pats) +{ + unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1, + z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3; + unsigned short tmp0, tmp1, tmp2, tmp3; + + z4_z1 = z4 ^ z1; + z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3); + z4_z2 = z4 ^ z2; + s0z4_s1 = gf4096_mul(s0, z4) ^ s1; + z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1); + z4_z3 = z4 ^ z3; + z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2); + s1z4_s2 = gf4096_mul(s1, z4) ^ s2; + z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3); + z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1); + z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2); + s2z4_s3 = gf4096_mul(s2, z4) ^ s3; + + //find err pat 0,1 + find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^ + gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2, + z3z4_z3z3) ^ + gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1, + z3z3z4_z3z3z3) ^ + gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3), + gf4096_mul(z2z4_z2z2, + z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2, + z3z4_z3z3), + gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2, + z4_z3), + gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats); + tmp0 = pats[0]; + tmp1 = pats[1]; + tmp2 = pats[0] ^ pats[1] ^ s0; + tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1; + + //find err pat 2,3 + find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats); + pats[2] = pats[0]; + pats[3] = pats[1]; + pats[0] = tmp0; + pats[1] = tmp1; +} + +static void find_2x2_soln(unsigned short c00, unsigned short c01, + unsigned short c10, unsigned short c11, + unsigned short lval0, unsigned short lval1, + unsigned short *soln) +{ + unsigned short m[2][3]; + m[0][0] = c00; + m[0][1] = c01; + m[0][2] = lval0; + m[1][0] = c10; + m[1][1] = c11; + m[1][2] = lval1; + + if (m[0][1] != 0x0) { + /* */ + } else if (m[1][1] != 0x0) { + swap_2x3_rows(m); + } else { + printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n"); + } + + solve_2x3(m, soln); +} + +static void swap_2x3_rows(unsigned short m[2][3]) +{ + unsigned short tmp0; + int cnt; + + for (cnt = 0; cnt < 3; cnt++) { + tmp0 = m[0][cnt]; + m[0][cnt] = m[1][cnt]; + m[1][cnt] = tmp0; + } +} + +static void solve_2x3(unsigned short m[2][3], unsigned short *coefs) +{ + unsigned short minv; + + minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1])); + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv); + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv); + coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0])); + coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1])); +} + +static unsigned char gf64_inv[64] = { + 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25, + 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6, + 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41, + 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32 +}; + +static unsigned short gf4096_inv(unsigned short din) +{ + unsigned short alahxal, ah2B, deno, inv, bl, bh; + unsigned short ah, al, ahxal; + unsigned short dout; + + ah = (din >> 6) & 0x3f; + al = din & 0x3f; + ahxal = ah ^ al; + ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) | + ((ah >> 1) & 0x10) | + ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) | + ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1); + alahxal = gf64_mul(ahxal, al); + deno = alahxal ^ ah2B; + inv = gf64_inv[deno]; + bl = gf64_mul(inv, ahxal); + bh = gf64_mul(inv, ah); + dout = ((bh & 0x3f) << 6) | (bl & 0x3f); + return (((bh & 0x3f) << 6) | (bl & 0x3f)); +} + +static unsigned short err_pos_lut[4096] = { + 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041, + 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff, + 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff, + 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7, + 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff, + 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff, + 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1, + 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff, + 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7, + 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff, + 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff, + 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d, + 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f, + 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8, + 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe, + 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff, + 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff, + 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1, + 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff, + 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff, + 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff, + 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff, + 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff, + 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff, + 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff, + 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8, + 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e, + 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff, + 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff, + 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff, + 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535, + 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d, + 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff, + 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5, + 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff, + 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294, + 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff, + 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4, + 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f, + 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b, + 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff, + 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff, + 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff, + 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff, + 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff, + 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158, + 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a, + 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff, + 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff, + 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017, + 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a, + 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351, + 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff, + 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3, + 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff, + 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074, + 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da, + 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433, + 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285, + 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff, + 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d, + 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff, + 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff, + 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331, + 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff, + 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6, + 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3, + 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff, + 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff, + 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf, + 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff, + 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc, + 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381, + 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff, + 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f, + 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff, + 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488, + 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442, + 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6, + 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1, + 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae, + 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff, + 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff, + 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff, + 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2, + 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec, + 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134, + 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b, + 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff, + 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff, + 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff, + 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff, + 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5, + 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff, + 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e, + 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff, + 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff, + 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff, + 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2, + 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff, + 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff, + 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff, + 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff, + 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff, + 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff, + 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff, + 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff, + 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8, + 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb, + 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff, + 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff, + 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd, + 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff, + 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8, + 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424, + 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9, + 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f, + 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7, + 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff, + 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d, + 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff, + 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178, + 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff, + 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba, + 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff, + 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e, + 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff, + 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6, + 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff, + 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff, + 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff, + 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc, + 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6, + 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5, + 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff, + 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff, + 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff, + 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc, + 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff, + 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff, + 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3, + 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff, + 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6, + 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff, + 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a, + 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff, + 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff, + 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb, + 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff, + 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff, + 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7, + 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff, + 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff, + 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af, + 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff, + 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff, + 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2, + 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff, + 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff, + 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff, + 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339, + 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff, + 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff, + 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402, + 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff, + 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff, + 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368, + 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff, + 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b, + 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f, + 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff, + 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1, + 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff, + 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff, + 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb, + 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc, + 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097, + 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431, + 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1, + 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4, + 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff, + 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff, + 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6, + 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd, + 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff, + 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb, + 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff, + 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd, + 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff, + 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff, + 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519, + 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff, + 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084, + 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0, + 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c, + 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff, + 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f, + 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a, + 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211, + 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff, + 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff, + 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff, + 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff, + 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff, + 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff, + 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180, + 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0, + 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004, + 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302, + 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff, + 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff, + 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072, + 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272, + 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff, + 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344, + 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff, + 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff, + 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e, + 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d, + 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff, + 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff, + 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330, + 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042, + 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364, + 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff, + 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff, + 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f, + 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb, + 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e, + 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c, + 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194, + 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff, + 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff, + 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff, + 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff, + 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff, + 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6, + 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff, + 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290, + 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff, + 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9, + 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d, + 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff, + 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9, + 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167, + 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020, + 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347, + 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff, + 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff, + 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff, + 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff, + 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff, + 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff, + 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039, + 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096, + 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff, + 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff, + 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff, + 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a, + 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8, + 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff, + 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd, + 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e, + 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f, + 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff, + 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff, + 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7, + 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb, + 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff, + 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff, + 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078, + 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300, + 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200, + 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f, + 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff, + 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216, + 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d, + 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0, + 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff, + 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff, + 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff, + 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff, + 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff, + 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff, + 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086, + 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff, + 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff, + 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444, + 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff, + 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff, + 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff, + 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110, + 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099, + 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff, + 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da, + 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff, + 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff, + 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff, + 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff, + 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff, + 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff, + 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283, + 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff, + 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff, + 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff, + 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff, + 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff, + 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195, + 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff, + 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff, + 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff, + 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff, + 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff, + 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245, + 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff, + 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6, + 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1, + 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da, + 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff, + 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff, + 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5, + 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223, + 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002 +}; + +static unsigned short err_pos(unsigned short din) +{ + BUG_ON(din >= ARRAY_SIZE(err_pos_lut)); + return err_pos_lut[din]; +} +static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + if ((chk_syndrome_list[0] | chk_syndrome_list[1] | + chk_syndrome_list[2] | chk_syndrome_list[3] | + chk_syndrome_list[4] | chk_syndrome_list[5] | + chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) { + return -EINVAL; + } else { + err_info[0] = 0x0; + return 0; + } +} +static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0])); + tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1])); + tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2])); + tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3])); + tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4])); + tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5])); + tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6])); + if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) { + err_info[0] = 0x1; // encode 1-symbol error as 0x1 + err_info[1] = err_pos(tmp0); + err_info[1] = (unsigned short)(0x55e - err_info[1]); + err_info[5] = chk_syndrome_list[0]; + return 0; + } else + return -EINVAL; +} +static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit2_root0, bit2_root1; + unsigned short bit2_root0_inv, bit2_root1_inv; + unsigned short err_loc_eqn, test_root; + unsigned short bit2_loc0, bit2_loc1; + unsigned short bit2_pat0, bit2_pat1; + + find_2x2_soln(chk_syndrome_list[1], + chk_syndrome_list[0], + chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs); + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = + gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1; + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit2_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit2_root1 = test_root; + found_num_root = 2; + break; + } + } + } + if (found_num_root != 2) + return -EINVAL; + else { + bit2_root0_inv = gf4096_inv(bit2_root0); + bit2_root1_inv = gf4096_inv(bit2_root1); + find_2bit_err_pats(chk_syndrome_list[0], + chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats); + bit2_pat0 = err_pats[0]; + bit2_pat1 = err_pats[1]; + //for(x+1) + tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4 + tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5 + tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6 + tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7 + tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4 + tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5 + tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6 + tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7 + //check if only 2-bit error + if ((chk_syndrome_list[4] == + (gf4096_mul(bit2_pat0, tmp0) ^ + gf4096_mul(bit2_pat1, + tmp4))) & (chk_syndrome_list[5] == + (gf4096_mul(bit2_pat0, tmp1) ^ + gf4096_mul(bit2_pat1, + tmp5))) & + (chk_syndrome_list[6] == + (gf4096_mul(bit2_pat0, tmp2) ^ + gf4096_mul(bit2_pat1, + tmp6))) & (chk_syndrome_list[7] == + (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) { + if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) { + return -EINVAL; + } else { + bit2_loc0 = 0x55e - err_pos(bit2_root0_inv); + bit2_loc1 = 0x55e - err_pos(bit2_root1_inv); + err_info[0] = 0x2; // encode 2-symbol error as 0x2 + err_info[1] = bit2_loc0; + err_info[2] = bit2_loc1; + err_info[5] = bit2_pat0; + err_info[6] = bit2_pat1; + return 0; + } + } else + return -EINVAL; + } +} +static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit3_root0, bit3_root1, bit3_root2; + unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv; + unsigned short err_loc_eqn, test_root; + + find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], chk_syndrome_list[3], + chk_syndrome_list[4], chk_syndrome_list[5], coefs); + + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = gf4096_mul(coefs[2], + gf4096_mul(gf4096_mul(test_root, test_root), + test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) + ^ gf4096_mul(coefs[0], test_root) ^ 0x1; + + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit3_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit3_root1 = test_root; + found_num_root = 2; + } else if (found_num_root == 2) { + bit3_root2 = test_root; + found_num_root = 3; + break; + } + } + } + if (found_num_root != 3) + return -EINVAL; + else { + bit3_root0_inv = gf4096_inv(bit3_root0); + bit3_root1_inv = gf4096_inv(bit3_root1); + bit3_root2_inv = gf4096_inv(bit3_root2); + + find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], bit3_root0_inv, + bit3_root1_inv, bit3_root2_inv, err_pats); + + //check if only 3-bit error + tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv); + tmp0 = gf4096_mul(tmp0, tmp0); + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6 + tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7 + tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv); + tmp2 = gf4096_mul(tmp2, tmp2); + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6 + tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7 + tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv); + tmp4 = gf4096_mul(tmp4, tmp4); + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6 + tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7 + + //check if only 3 errors + if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^ + gf4096_mul(err_pats[1], tmp2) ^ + gf4096_mul(err_pats[2], tmp4))) & + (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^ + gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) { + if ((err_pos(bit3_root0_inv) == 0xfff) | + (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) { + return -EINVAL; + } else { + err_info[0] = 0x3; + err_info[1] = (0x55e - err_pos(bit3_root0_inv)); + err_info[2] = (0x55e - err_pos(bit3_root1_inv)); + err_info[3] = (0x55e - err_pos(bit3_root2_inv)); + err_info[5] = err_pats[0]; + err_info[6] = err_pats[1]; + err_info[7] = err_pats[2]; + return 0; + } + } else + return -EINVAL; + } +} +static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3; + unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv; + unsigned short err_loc_eqn, test_root; + + find_4bit_err_coefs(chk_syndrome_list[0], + chk_syndrome_list[1], + chk_syndrome_list[2], + chk_syndrome_list[3], + chk_syndrome_list[4], + chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs); + + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = + gf4096_mul(coefs[3], + gf4096_mul(gf4096_mul + (gf4096_mul(test_root, test_root), + test_root), + test_root)) ^ gf4096_mul(coefs[2], + gf4096_mul + (gf4096_mul(test_root, test_root), test_root)) + ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) + ^ 0x1; + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit4_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit4_root1 = test_root; + found_num_root = 2; + } else if (found_num_root == 2) { + bit4_root2 = test_root; + found_num_root = 3; + } else { + found_num_root = 4; + bit4_root3 = test_root; + break; + } + } + } + if (found_num_root != 4) { + return -EINVAL; + } else { + bit4_root0_inv = gf4096_inv(bit4_root0); + bit4_root1_inv = gf4096_inv(bit4_root1); + bit4_root2_inv = gf4096_inv(bit4_root2); + bit4_root3_inv = gf4096_inv(bit4_root3); + find_4bit_err_pats(chk_syndrome_list[0], + chk_syndrome_list[1], + chk_syndrome_list[2], + chk_syndrome_list[3], + bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats); + err_info[0] = 0x4; + err_info[1] = (0x55e - err_pos(bit4_root0_inv)); + err_info[2] = (0x55e - err_pos(bit4_root1_inv)); + err_info[3] = (0x55e - err_pos(bit4_root2_inv)); + err_info[4] = (0x55e - err_pos(bit4_root3_inv)); + err_info[5] = err_pats[0]; + err_info[6] = err_pats[1]; + err_info[7] = err_pats[2]; + err_info[8] = err_pats[3]; + return 0; + } +} + +void correct_12bit_symbol(unsigned char *buf, unsigned short sym, + unsigned short val) +{ + if (unlikely(sym > 1366)) { + printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym); + } else if (sym == 0) { + buf[0] ^= val; + } else if (sym & 1) { + buf[1+(3*(sym-1))/2] ^= (val >> 4); + buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4); + } else { + buf[2+(3*(sym-2))/2] ^= (val >> 8); + buf[3+(3*(sym-2))/2] ^= (val & 0xff); + } +} + +static int debugecc = 0; +module_param(debugecc, int, 0644); + +int cafe_correct_ecc(unsigned char *buf, + unsigned short *chk_syndrome_list) +{ + unsigned short err_info[9]; + int i; + + if (debugecc) { + printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n", + chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], chk_syndrome_list[3], + chk_syndrome_list[4], chk_syndrome_list[5], + chk_syndrome_list[6], chk_syndrome_list[7]); + for (i=0; i < 2048; i+=16) { + printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, + buf[i], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + for ( ; i < 2112; i+=16) { + printk(KERN_WARNING "O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i - 2048, + buf[i], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + } + + + + if (chk_no_err_only(chk_syndrome_list, err_info) && + chk_1_err_only(chk_syndrome_list, err_info) && + chk_2_err_only(chk_syndrome_list, err_info) && + chk_3_err_only(chk_syndrome_list, err_info) && + chk_4_err_only(chk_syndrome_list, err_info)) { + return -EIO; + } + + for (i=0; i < err_info[0]; i++) { + if (debugecc) + printk(KERN_WARNING "Correct symbol %d with 0x%03x\n", + err_info[1+i], err_info[5+i]); + + correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]); + } + + return err_info[0]; +} + diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index 7e68203fe1ba..04de315e4937 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -303,27 +303,28 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) struct nand_chip *chip = mtd->priv; u16 bad; - page = (int)(ofs >> chip->page_shift) & chip->pagemask; - if (getchip) { + page = (int)(ofs >> chip->page_shift); chipnr = (int)(ofs >> chip->chip_shift); nand_get_device(chip, mtd, FL_READING); /* Select the NAND device */ chip->select_chip(mtd, chipnr); - } + } else + page = (int)(ofs >> chip->page_shift); if (chip->options & NAND_BUSWIDTH_16) { chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, - page); + page & chip->pagemask); bad = cpu_to_le16(chip->read_word(mtd)); if (chip->badblockpos & 0x1) bad >>= 8; if ((bad & 0xFF) != 0xff) res = 1; } else { - chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); + chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, + page & chip->pagemask); if (chip->read_byte(mtd) != 0xff) res = 1; } diff --git a/trunk/drivers/mtd/nand/plat_nand.c b/trunk/drivers/mtd/nand/plat_nand.c deleted file mode 100644 index cd725fc5e813..000000000000 --- a/trunk/drivers/mtd/nand/plat_nand.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Generic NAND driver - * - * Author: Vitaly Wool - * - * 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 - -struct plat_nand_data { - struct nand_chip chip; - struct mtd_info mtd; - void __iomem *io_base; -#ifdef CONFIG_MTD_PARTITIONS - int nr_parts; - struct mtd_partition *parts; -#endif -}; - -/* - * Probe for the NAND device. - */ -static int __init plat_nand_probe(struct platform_device *pdev) -{ - struct platform_nand_data *pdata = pdev->dev.platform_data; - struct plat_nand_data *data; - int res = 0; - - /* Allocate memory for the device structure (and zero it) */ - data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL); - if (!data) { - dev_err(&pdev->dev, "failed to allocate device structure.\n"); - return -ENOMEM; - } - - data->io_base = ioremap(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1); - if (data->io_base == NULL) { - dev_err(&pdev->dev, "ioremap failed\n"); - kfree(data); - return -EIO; - } - - data->chip.priv = &data; - data->mtd.priv = &data->chip; - data->mtd.owner = THIS_MODULE; - - data->chip.IO_ADDR_R = data->io_base; - data->chip.IO_ADDR_W = data->io_base; - data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; - data->chip.dev_ready = pdata->ctrl.dev_ready; - data->chip.select_chip = pdata->ctrl.select_chip; - data->chip.chip_delay = pdata->chip.chip_delay; - data->chip.options |= pdata->chip.options; - - data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; - data->chip.ecc.layout = pdata->chip.ecclayout; - data->chip.ecc.mode = NAND_ECC_SOFT; - - platform_set_drvdata(pdev, data); - - /* Scan to find existance of the device */ - if (nand_scan(&data->mtd, 1)) { - res = -ENXIO; - goto out; - } - -#ifdef CONFIG_MTD_PARTITIONS - if (pdata->chip.part_probe_types) { - res = parse_mtd_partitions(&data->mtd, - pdata->chip.part_probe_types, - &data->parts, 0); - if (res > 0) { - add_mtd_partitions(&data->mtd, data->parts, res); - return 0; - } - } - if (pdata->chip.partitions) { - data->parts = pdata->chip.partitions; - res = add_mtd_partitions(&data->mtd, data->parts, - pdata->chip.nr_partitions); - } else -#endif - res = add_mtd_device(&data->mtd); - - if (!res) - return res; - - nand_release(&data->mtd); -out: - platform_set_drvdata(pdev, NULL); - iounmap(data->io_base); - kfree(data); - return res; -} - -/* - * Remove a NAND device. - */ -static int __devexit plat_nand_remove(struct platform_device *pdev) -{ - struct plat_nand_data *data = platform_get_drvdata(pdev); - struct platform_nand_data *pdata = pdev->dev.platform_data; - - nand_release(&data->mtd); -#ifdef CONFIG_MTD_PARTITIONS - if (data->parts && data->parts != pdata->chip.partitions) - kfree(data->parts); -#endif - iounmap(data->io_base); - kfree(data); - - return 0; -} - -static struct platform_driver plat_nand_driver = { - .probe = plat_nand_probe, - .remove = plat_nand_remove, - .driver = { - .name = "gen_nand", - .owner = THIS_MODULE, - }, -}; - -static int __init plat_nand_init(void) -{ - return platform_driver_register(&plat_nand_driver); -} - -static void __exit plat_nand_exit(void) -{ - platform_driver_unregister(&plat_nand_driver); -} - -module_init(plat_nand_init); -module_exit(plat_nand_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vitaly Wool"); -MODULE_DESCRIPTION("Simple generic NAND driver"); diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index 0537fac8de74..000794c6caf5 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -2192,7 +2192,7 @@ static int onenand_check_maf(int manuf) * @param mtd MTD device structure * * OneNAND detection method: - * Compare the values from command with ones from register + * Compare the the values from command with ones from register */ static int onenand_probe(struct mtd_info *mtd) { diff --git a/trunk/drivers/net/3c509.c b/trunk/drivers/net/3c509.c index 127f60841b10..9588da3a30e7 100644 --- a/trunk/drivers/net/3c509.c +++ b/trunk/drivers/net/3c509.c @@ -95,7 +95,8 @@ static int max_interrupt_work = 10; #include #include -static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n"; #if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA)) #define EL3_SUSPEND @@ -359,7 +360,7 @@ static int __init el3_common_init(struct net_device *dev) printk(", IRQ %d.\n", dev->irq); if (el3_debug > 0) - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return 0; } diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index f26ca331615e..80924f76dee8 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -103,7 +103,7 @@ static int vortex_debug = 1; static char version[] __devinitdata = -DRV_NAME ": Donald Becker and others.\n"; +DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver "); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index fa489b10c38c..b86ccd2ecd5b 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2493,28 +2493,12 @@ config PASEMI_MAC This driver supports the on-chip 1/10Gbit Ethernet controller on PA Semi's PWRficient line of chips. -config MLX4_CORE - tristate - depends on PCI - default n - -config MLX4_DEBUG - bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED) - default y - ---help--- - This option causes debugging code to be compiled into the - mlx4_core driver. The output can be turned on via the - debug_level module parameter (which can also be set after - the driver is loaded through sysfs). - endmenu source "drivers/net/tokenring/Kconfig" source "drivers/net/wireless/Kconfig" -source "drivers/net/usb/Kconfig" - source "drivers/net/pcmcia/Kconfig" source "drivers/net/wan/Kconfig" diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index a77affa4f6e6..59c0459a037c 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -197,7 +197,6 @@ obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o -obj-$(CONFIG_MLX4_CORE) += mlx4/ obj-$(CONFIG_MACB) += macb.o @@ -207,14 +206,6 @@ obj-$(CONFIG_TR) += tokenring/ obj-$(CONFIG_WAN) += wan/ obj-$(CONFIG_ARCNET) += arcnet/ obj-$(CONFIG_NET_PCMCIA) += pcmcia/ - -obj-$(CONFIG_USB_CATC) += usb/ -obj-$(CONFIG_USB_KAWETH) += usb/ -obj-$(CONFIG_USB_PEGASUS) += usb/ -obj-$(CONFIG_USB_RTL8150) += usb/ -obj-$(CONFIG_USB_USBNET) += usb/ -obj-$(CONFIG_USB_ZD1201) += usb/ - obj-y += wireless/ obj-$(CONFIG_NET_TULIP) += tulip/ obj-$(CONFIG_HAMRADIO) += hamradio/ diff --git a/trunk/drivers/net/atl1/atl1_main.c b/trunk/drivers/net/atl1/atl1_main.c index 78cf00ff3d38..d28f88bbdd5f 100644 --- a/trunk/drivers/net/atl1/atl1_main.c +++ b/trunk/drivers/net/atl1/atl1_main.c @@ -2038,15 +2038,6 @@ static int atl1_close(struct net_device *netdev) return 0; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void atl1_poll_controller(struct net_device *netdev) -{ - disable_irq(netdev->irq); - atl1_intr(netdev->irq, netdev); - enable_irq(netdev->irq); -} -#endif - /* * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT * will assert. We do soft reset <0x1400=1> according @@ -2199,9 +2190,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->do_ioctl = &atl1_ioctl; netdev->tx_timeout = &atl1_tx_timeout; netdev->watchdog_timeo = 5 * HZ; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = atl1_poll_controller; -#endif netdev->vlan_rx_register = atl1_vlan_rx_register; netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid; diff --git a/trunk/drivers/net/atp.c b/trunk/drivers/net/atp.c index 82d78ff8399b..18aba838c1ff 100644 --- a/trunk/drivers/net/atp.c +++ b/trunk/drivers/net/atp.c @@ -31,8 +31,10 @@ */ -static const char version[] = +static const char versionA[] = "atp.c:v1.09=ac 2002/10/01 Donald Becker \n"; +static const char versionB[] = +" http://www.scyld.com/network/atp.html\n"; /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -322,7 +324,7 @@ static int __init atp_probe1(long ioaddr) #ifndef MODULE if (net_debug) - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); #endif printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, SAPROM " @@ -924,7 +926,7 @@ static void set_rx_mode_8012(struct net_device *dev) static int __init atp_init_module(void) { if (debug) /* Emit version even if no cards detected. */ - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return atp_init(); } diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 223517dcbcfd..724bce51f936 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -3461,7 +3461,7 @@ void bond_unregister_arp(struct bonding *bond) /*---------------------------- Hashing Policies -----------------------------*/ /* - * Hash for the output device based upon layer 3 and layer 4 data. If + * Hash for the the output device based upon layer 3 and layer 4 data. If * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is * altogether not IP, mimic bond_xmit_hash_policy_l2() */ diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 637ae8f68791..3a03a74c0609 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -1214,7 +1214,7 @@ e1000_remove(struct pci_dev *pdev) int i; #endif - cancel_work_sync(&adapter->reset_task); + flush_scheduled_work(); e1000_release_manageability(adapter); diff --git a/trunk/drivers/net/eepro.c b/trunk/drivers/net/eepro.c index 47680237f783..39654e1e2bed 100644 --- a/trunk/drivers/net/eepro.c +++ b/trunk/drivers/net/eepro.c @@ -1126,7 +1126,7 @@ static void eepro_tx_timeout (struct net_device *dev) printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); /* This is not a duplicate. One message for the console, - one for the log file */ + one for the the log file */ printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); eepro_complete_selreset(ioaddr); diff --git a/trunk/drivers/net/eepro100.c b/trunk/drivers/net/eepro100.c index 9800341956a2..6c267c38df97 100644 --- a/trunk/drivers/net/eepro100.c +++ b/trunk/drivers/net/eepro100.c @@ -28,7 +28,7 @@ */ static const char * const version = -"eepro100.c:v1.09j-t 9/29/99 Donald Becker\n" +"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n" "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin and others\n"; /* A few user-configurable values that apply to all boards. diff --git a/trunk/drivers/net/epic100.c b/trunk/drivers/net/epic100.c index 5e517946f46a..4e3f14c9c717 100644 --- a/trunk/drivers/net/epic100.c +++ b/trunk/drivers/net/epic100.c @@ -93,6 +93,8 @@ static int rx_copybreak; static char version[] __devinitdata = DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker \n"; static char version2[] __devinitdata = +" http://www.scyld.com/network/epic100.html\n"; +static char version3[] __devinitdata = " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); @@ -321,8 +323,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev, #ifndef MODULE static int printed_version; if (!printed_version++) - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", + version, version2, version3); #endif card_idx++; @@ -1594,8 +1596,8 @@ static int __init epic_init (void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", + version, version2, version3); #endif return pci_register_driver(&epic_driver); diff --git a/trunk/drivers/net/fs_enet/mac-scc.c b/trunk/drivers/net/fs_enet/mac-scc.c index 7540966687ec..d0f28981b55a 100644 --- a/trunk/drivers/net/fs_enet/mac-scc.c +++ b/trunk/drivers/net/fs_enet/mac-scc.c @@ -167,7 +167,7 @@ static int allocate_bd(struct net_device *dev) fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t), 8); - if (IS_ERR_VALUE(fep->ring_mem_addr)) + if (IS_DPERR(fep->ring_mem_addr)) return -ENOMEM; fep->ring_base = cpm_dpram_addr(fep->ring_mem_addr); diff --git a/trunk/drivers/net/hamradio/Kconfig b/trunk/drivers/net/hamradio/Kconfig index 36d2c7d4f4d0..6e90619b3b41 100644 --- a/trunk/drivers/net/hamradio/Kconfig +++ b/trunk/drivers/net/hamradio/Kconfig @@ -140,7 +140,7 @@ config BAYCOM_SER_HDX modems that connect to a serial interface. The driver supports the ser12 design in half-duplex mode. This is the old driver. It is still provided in case your serial interface chip does not work with - the full-duplex driver. This driver is deprecated. To configure + the full-duplex driver. This driver is depreciated. To configure the driver, use the sethdlc utility available in the standard ax25 utilities package. For information on the modems, see and diff --git a/trunk/drivers/net/irda/Kconfig b/trunk/drivers/net/irda/Kconfig index 829da9a1d113..7c8ccc09b601 100644 --- a/trunk/drivers/net/irda/Kconfig +++ b/trunk/drivers/net/irda/Kconfig @@ -141,20 +141,6 @@ config ACT200L_DONGLE To activate support for ACTiSYS IR-200L dongle you will have to start irattach like this: "irattach -d act200l". -config KINGSUN_DONGLE - tristate "KingSun/DonShine DS-620 IrDA-USB dongle" - depends on IRDA && USB && EXPERIMENTAL - help - Say Y or M here if you want to build support for the KingSun/DonShine - DS-620 IrDA-USB bridge device driver. - - This USB bridge does not conform to the IrDA-USB device class - specification, and therefore needs its own specific driver. This - dongle supports SIR speed only (9600 bps). - - To compile it as a module, choose M here: the module will be called - kingsun-sir. - comment "Old SIR device drivers" config IRPORT_SIR diff --git a/trunk/drivers/net/irda/Makefile b/trunk/drivers/net/irda/Makefile index 233a2f923730..5be09f1b9ee2 100644 --- a/trunk/drivers/net/irda/Makefile +++ b/trunk/drivers/net/irda/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o -obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o # The SIR helper module sir-dev-objs := sir_dev.o sir_dongle.o diff --git a/trunk/drivers/net/irda/donauboe.h b/trunk/drivers/net/irda/donauboe.h index 1e67720f1066..2ab173d9a0e4 100644 --- a/trunk/drivers/net/irda/donauboe.h +++ b/trunk/drivers/net/irda/donauboe.h @@ -113,7 +113,7 @@ /* RxOver overflow in Recv FIFO */ /* SipRcv received serial gap (or other condition you set) */ /* Interrupts are enabled by writing a one to the IER register */ -/* Interrupts are cleared by writing a one to the ISR register */ +/* Interrupts are cleared by writting a one to the ISR register */ /* */ /* 6. The remaining registers: 0x6 and 0x3 appear to be */ /* reserved parts of 16 or 32 bit registersthe remainder */ diff --git a/trunk/drivers/net/irda/kingsun-sir.c b/trunk/drivers/net/irda/kingsun-sir.c deleted file mode 100644 index 217429122e79..000000000000 --- a/trunk/drivers/net/irda/kingsun-sir.c +++ /dev/null @@ -1,657 +0,0 @@ -/***************************************************************************** -* -* Filename: kingsun-sir.c -* Version: 0.1.1 -* Description: Irda KingSun/DonShine USB Dongle -* Status: Experimental -* Author: Alex Villac�s Lasso -* -* Based on stir4200 and mcs7780 drivers, with (strange?) differences -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License. -* -* This program is 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. -* -*****************************************************************************/ - -/* - * This is my current (2007-04-25) understanding of how this dongle is supposed - * to work. This is based on reverse-engineering and examination of the packet - * data sent and received by the WinXP driver using USBSnoopy. Feel free to - * update here as more of this dongle is known: - * - * General: Unlike the other USB IrDA dongles, this particular dongle exposes, - * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle, - * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in - * order to receive data. - * Transmission: Just like stir4200, this dongle uses a raw stream of data, - * which needs to be wrapped and escaped in a similar way as in stir4200.c. - * Reception: Poll-based, as in stir4200. Each read returns the contents of a - * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes - * (1-7) of valid data contained within the remaining 7 bytes. For example, if - * the buffer had the following contents: - * 06 ff ff ff c0 01 04 aa - * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the - * end is garbage (left over from a previous reception) and is discarded. - * If a read returns an "impossible" value as the length of valid data (such as - * 0x36) in the first byte, then the buffer is uninitialized (as is the case of - * first plug-in) and its contents should be discarded. There is currently no - * evidence that the top 5 bits of the 1st byte of the buffer can have values - * other than 0 once reception begins. - * Once valid bytes are collected, the assembled stream is a sequence of - * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c. - * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after - * a successful read from the host, which means that in absence of further - * reception, repeated reads from the dongle will return the exact same - * contents repeatedly. Attempts to be smart and cache a previous read seem - * to result in corrupted packets, so this driver depends on the unwrap logic - * to sort out any repeated reads. - * Speed change: no commands observed so far to change speed, assumed fixed - * 9600bps (SIR). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* - * According to lsusb, 0x07c0 is assigned to - * "Code Mercenaries Hard- und Software GmbH" - */ -#define KING_VENDOR_ID 0x07c0 -#define KING_PRODUCT_ID 0x4200 - -/* These are the currently known USB ids */ -static struct usb_device_id dongles[] = { - /* KingSun Co,Ltd IrDA/USB Bridge */ - { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, dongles); - -#define KINGSUN_MTT 0x07 - -#define KINGSUN_FIFO_SIZE 4096 -#define KINGSUN_EP_IN 0 -#define KINGSUN_EP_OUT 1 - -struct kingsun_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - struct net_device_stats stats; /* network statistics */ - struct qos_info qos; - - __u8 *in_buf; /* receive buffer */ - __u8 *out_buf; /* transmit buffer */ - __u8 max_rx; /* max. atomic read from dongle - (usually 8), also size of in_buf */ - __u8 max_tx; /* max. atomic write to dongle - (usually 8) */ - - iobuff_t rx_buff; /* receive unwrap state machine */ - struct timeval rx_time; - spinlock_t lock; - int receiving; - - __u8 ep_in; - __u8 ep_out; - - struct urb *tx_urb; - struct urb *rx_urb; -}; - -/* Callback transmission routine */ -static void kingsun_send_irq(struct urb *urb) -{ - struct kingsun_cb *kingsun = urb->context; - struct net_device *netdev = kingsun->netdev; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - err("kingsun_send_irq: Network not running!"); - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - err("kingsun_send_irq: urb asynchronously failed - %d", - urb->status); - } - netif_wake_queue(netdev); -} - -/* - * Called from net/core when new frame is available. - */ -static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct kingsun_cb *kingsun; - int wraplen; - int ret = 0; - - if (skb == NULL || netdev == NULL) - return -EINVAL; - - netif_stop_queue(netdev); - - /* the IRDA wrapping routines don't deal with non linear skb */ - SKB_LINEAR_ASSERT(skb); - - kingsun = netdev_priv(netdev); - - spin_lock(&kingsun->lock); - - /* Append data to the end of whatever data remains to be transmitted */ - wraplen = async_wrap_skb(skb, - kingsun->out_buf, - KINGSUN_FIFO_SIZE); - - /* Calculate how much data can be transmitted in this urb */ - usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, - usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), - kingsun->out_buf, wraplen, kingsun_send_irq, - kingsun, 1); - - if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) { - err("kingsun_hard_xmit: failed tx_urb submit: %d", ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - kingsun->stats.tx_errors++; - netif_start_queue(netdev); - } - } else { - kingsun->stats.tx_packets++; - kingsun->stats.tx_bytes += skb->len; - } - - dev_kfree_skb(skb); - spin_unlock(&kingsun->lock); - - return ret; -} - -/* Receive callback function */ -static void kingsun_rcv_irq(struct urb *urb) -{ - struct kingsun_cb *kingsun = urb->context; - int ret; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - kingsun->receiving = 0; - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - err("kingsun_rcv_irq: urb asynchronously failed - %d", - urb->status); - kingsun->receiving = 0; - return; - } - - if (urb->actual_length == kingsun->max_rx) { - __u8 *bytes = urb->transfer_buffer; - int i; - - /* The very first byte in the buffer indicates the length of - valid data in the read. This byte must be in the range - 1..kingsun->max_rx -1 . Values outside this range indicate - an uninitialized Rx buffer when the dongle has just been - plugged in. */ - if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) { - for (i = 1; i <= bytes[0]; i++) { - async_unwrap_char(kingsun->netdev, - &kingsun->stats, - &kingsun->rx_buff, bytes[i]); - } - kingsun->netdev->last_rx = jiffies; - do_gettimeofday(&kingsun->rx_time); - kingsun->receiving = - (kingsun->rx_buff.state != OUTSIDE_FRAME) - ? 1 : 0; - } - } else if (urb->actual_length > 0) { - err("%s(): Unexpected response length, expected %d got %d", - __FUNCTION__, kingsun->max_rx, urb->actual_length); - } - /* This urb has already been filled in kingsun_net_open */ - ret = usb_submit_urb(urb, GFP_ATOMIC); -} - -/* - * Function kingsun_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - */ -static int kingsun_net_open(struct net_device *netdev) -{ - struct kingsun_cb *kingsun = netdev_priv(netdev); - int err = -ENOMEM; - char hwname[16]; - - /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ - kingsun->receiving = 0; - - /* Initialize for SIR to copy data directly into skb. */ - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU; - kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!kingsun->rx_buff.skb) - goto free_mem; - - skb_reserve(kingsun->rx_buff.skb, 1); - kingsun->rx_buff.head = kingsun->rx_buff.skb->data; - do_gettimeofday(&kingsun->rx_time); - - kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->rx_urb) - goto free_mem; - - kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->tx_urb) - goto free_mem; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - */ - sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); - kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); - if (!kingsun->irlap) { - err("kingsun-sir: irlap_open failed"); - goto free_mem; - } - - /* Start first reception */ - usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, - usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), - kingsun->in_buf, kingsun->max_rx, - kingsun_rcv_irq, kingsun, 1); - kingsun->rx_urb->status = 0; - err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - if (err) { - err("kingsun-sir: first urb-submit failed: %d", err); - goto close_irlap; - } - - netif_start_queue(netdev); - - /* Situation at this point: - - all work buffers allocated - - urbs allocated and ready to fill - - max rx packet known (in max_rx) - - unwrap state machine initialized, in state outside of any frame - - receive request in progress - - IrLAP layer started, about to hand over packets to send - */ - - return 0; - - close_irlap: - irlap_close(kingsun->irlap); - free_mem: - if (kingsun->tx_urb) { - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - } - if (kingsun->rx_urb) { - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - } - if (kingsun->rx_buff.skb) { - kfree_skb(kingsun->rx_buff.skb); - kingsun->rx_buff.skb = NULL; - kingsun->rx_buff.head = NULL; - } - return err; -} - -/* - * Function kingsun_net_close (kingsun) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int kingsun_net_close(struct net_device *netdev) -{ - struct kingsun_cb *kingsun = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - /* Mop up receive && transmit urb's */ - usb_kill_urb(kingsun->tx_urb); - usb_kill_urb(kingsun->rx_urb); - - usb_free_urb(kingsun->tx_urb); - usb_free_urb(kingsun->rx_urb); - - kingsun->tx_urb = NULL; - kingsun->rx_urb = NULL; - - kfree_skb(kingsun->rx_buff.skb); - kingsun->rx_buff.skb = NULL; - kingsun->rx_buff.head = NULL; - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->receiving = 0; - - /* Stop and remove instance of IrLAP */ - if (kingsun->irlap) - irlap_close(kingsun->irlap); - - kingsun->irlap = NULL; - - return 0; -} - -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq, - int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct kingsun_cb *kingsun = netdev_priv(netdev); - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the device is still there */ - if (netif_device_present(kingsun->netdev)) - /* No observed commands for speed change */ - ret = -EOPNOTSUPP; - break; - - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the IrDA stack is still there */ - if (netif_running(kingsun->netdev)) - irda_device_set_media_busy(kingsun->netdev, TRUE); - break; - - case SIOCGRECEIVING: - /* Only approximately true */ - irq->ifr_receiving = kingsun->receiving; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -/* - * Get device stats (for /proc/net/dev and ifconfig) - */ -static struct net_device_stats * -kingsun_net_get_stats(struct net_device *netdev) -{ - struct kingsun_cb *kingsun = netdev_priv(netdev); - return &kingsun->stats; -} - -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - */ -static int kingsun_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - - struct usb_device *dev = interface_to_usbdev(intf); - struct kingsun_cb *kingsun = NULL; - struct net_device *net = NULL; - int ret = -ENOMEM; - int pipe, maxp_in, maxp_out; - __u8 ep_in; - __u8 ep_out; - - /* Check that there really are two interrupt endpoints. - Check based on the one in drivers/usb/input/usbmouse.c - */ - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 2) { - err("kingsun-sir: expected 2 endpoints, found %d", - interface->desc.bNumEndpoints); - return -ENODEV; - } - endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; - if (!usb_endpoint_is_int_in(endpoint)) { - err("kingsun-sir: endpoint 0 is not interrupt IN"); - return -ENODEV; - } - - ep_in = endpoint->bEndpointAddress; - pipe = usb_rcvintpipe(dev, ep_in); - maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (maxp_in > 255 || maxp_in <= 1) { - err("%s: endpoint 0 has max packet size %d not in range", - __FILE__, maxp_in); - return -ENODEV; - } - - endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; - if (!usb_endpoint_is_int_out(endpoint)) { - err("kingsun-sir: endpoint 1 is not interrupt OUT"); - return -ENODEV; - } - - ep_out = endpoint->bEndpointAddress; - pipe = usb_sndintpipe(dev, ep_out); - maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - /* Allocate network device container. */ - net = alloc_irdadev(sizeof(*kingsun)); - if(!net) - goto err_out1; - - SET_MODULE_OWNER(net); - SET_NETDEV_DEV(net, &intf->dev); - kingsun = netdev_priv(net); - kingsun->irlap = NULL; - kingsun->tx_urb = NULL; - kingsun->rx_urb = NULL; - kingsun->ep_in = ep_in; - kingsun->ep_out = ep_out; - kingsun->in_buf = NULL; - kingsun->out_buf = NULL; - kingsun->max_rx = (__u8)maxp_in; - kingsun->max_tx = (__u8)maxp_out; - kingsun->netdev = net; - kingsun->usbdev = dev; - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->rx_buff.skb = NULL; - kingsun->receiving = 0; - spin_lock_init(&kingsun->lock); - - /* Allocate input buffer */ - kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL); - if (!kingsun->in_buf) - goto free_mem; - - /* Allocate output buffer */ - kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); - if (!kingsun->out_buf) - goto free_mem; - - printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " - "Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&kingsun->qos); - - /* That's the Rx capability. */ - kingsun->qos.baud_rate.bits &= IR_9600; - kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; - irda_qos_bits_to_value(&kingsun->qos); - - /* Override the network functions we need to use */ - net->hard_start_xmit = kingsun_hard_xmit; - net->open = kingsun_net_open; - net->stop = kingsun_net_close; - net->get_stats = kingsun_net_get_stats; - net->do_ioctl = kingsun_net_ioctl; - - ret = register_netdev(net); - if (ret != 0) - goto free_mem; - - info("IrDA: Registered KingSun/DonShine device %s", net->name); - - usb_set_intfdata(intf, kingsun); - - /* Situation at this point: - - all work buffers allocated - - urbs not allocated, set to NULL - - max rx packet known (in max_rx) - - unwrap state machine (partially) initialized, but skb == NULL - */ - - return 0; - -free_mem: - if (kingsun->out_buf) kfree(kingsun->out_buf); - if (kingsun->in_buf) kfree(kingsun->in_buf); - free_netdev(net); -err_out1: - return ret; -} - -/* - * The current device is removed, the USB layer tell us to shut it down... - */ -static void kingsun_disconnect(struct usb_interface *intf) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - if (!kingsun) - return; - - unregister_netdev(kingsun->netdev); - - /* Mop up receive && transmit urb's */ - if (kingsun->tx_urb != NULL) { - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - } - if (kingsun->rx_urb != NULL) { - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - } - - kfree(kingsun->out_buf); - kfree(kingsun->in_buf); - free_netdev(kingsun->netdev); - - usb_set_intfdata(intf, NULL); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int kingsun_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - netif_device_detach(kingsun->netdev); - if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb); - if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb); - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int kingsun_resume(struct usb_interface *intf) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - if (kingsun->rx_urb != NULL) - usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - netif_device_attach(kingsun->netdev); - - return 0; -} -#endif - -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "kingsun-sir", - .probe = kingsun_probe, - .disconnect = kingsun_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = kingsun_suspend, - .resume = kingsun_resume, -#endif -}; - -/* - * Module insertion - */ -static int __init kingsun_init(void) -{ - return usb_register(&irda_driver); -} -module_init(kingsun_init); - -/* - * Module removal - */ -static void __exit kingsun_cleanup(void) -{ - /* Deregister the driver and remove all pending instances */ - usb_deregister(&irda_driver); -} -module_exit(kingsun_cleanup); - -MODULE_AUTHOR("Alex Villac�s Lasso "); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/ixgb/ixgb_ee.c b/trunk/drivers/net/ixgb/ixgb_ee.c index 52c99d01d568..f15aebde7b90 100644 --- a/trunk/drivers/net/ixgb/ixgb_ee.c +++ b/trunk/drivers/net/ixgb/ixgb_ee.c @@ -315,7 +315,7 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw) * hw - Struct containing variables accessed by shared code * * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is + * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is * valid. * * Returns: diff --git a/trunk/drivers/net/meth.h b/trunk/drivers/net/meth.h index ea3b8fc86d1e..84960dae2a22 100644 --- a/trunk/drivers/net/meth.h +++ b/trunk/drivers/net/meth.h @@ -126,7 +126,7 @@ typedef struct rx_packet { /* Note: when loopback is set this bit becomes collision control. Setting this bit will */ /* cause a collision to be reported. */ - /* Bits 5 and 6 are used to determine the Destination address filter mode */ + /* Bits 5 and 6 are used to determine the the Destination address filter mode */ #define METH_ACCEPT_MY 0 /* 00: Accept PHY address only */ #define METH_ACCEPT_MCAST 0x20 /* 01: Accept physical, broadcast, and multicast filter matches only */ #define METH_ACCEPT_AMCAST 0x40 /* 10: Accept physical, broadcast, and all multicast packets */ diff --git a/trunk/drivers/net/mlx4/Makefile b/trunk/drivers/net/mlx4/Makefile deleted file mode 100644 index 0952a6528f58..000000000000 --- a/trunk/drivers/net/mlx4/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_MLX4_CORE) += mlx4_core.o - -mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ - mr.o pd.o profile.o qp.o reset.o srq.o diff --git a/trunk/drivers/net/mlx4/alloc.c b/trunk/drivers/net/mlx4/alloc.c deleted file mode 100644 index 9ffdb9d29da9..000000000000 --- a/trunk/drivers/net/mlx4/alloc.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" - -u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) -{ - u32 obj; - - spin_lock(&bitmap->lock); - - obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); - if (obj >= bitmap->max) { - bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; - obj = find_first_zero_bit(bitmap->table, bitmap->max); - } - - if (obj < bitmap->max) { - set_bit(obj, bitmap->table); - obj |= bitmap->top; - bitmap->last = obj + 1; - } else - obj = -1; - - spin_unlock(&bitmap->lock); - - return obj; -} - -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) -{ - obj &= bitmap->max - 1; - - spin_lock(&bitmap->lock); - clear_bit(obj, bitmap->table); - bitmap->last = min(bitmap->last, obj); - bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; - spin_unlock(&bitmap->lock); -} - -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved) -{ - int i; - - /* num must be a power of 2 */ - if (num != roundup_pow_of_two(num)) - return -EINVAL; - - bitmap->last = 0; - bitmap->top = 0; - bitmap->max = num; - bitmap->mask = mask; - spin_lock_init(&bitmap->lock); - bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL); - if (!bitmap->table) - return -ENOMEM; - - for (i = 0; i < reserved; ++i) - set_bit(i, bitmap->table); - - return 0; -} - -void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap) -{ - kfree(bitmap->table); -} - -/* - * Handling for queue buffers -- we allocate a bunch of memory and - * register it in a memory region at HCA virtual address 0. If the - * requested size is > max_direct, we split the allocation into - * multiple pages, so we don't require too much contiguous memory. - */ - -int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, - struct mlx4_buf *buf) -{ - dma_addr_t t; - - if (size <= max_direct) { - buf->nbufs = 1; - buf->npages = 1; - buf->page_shift = get_order(size) + PAGE_SHIFT; - buf->u.direct.buf = dma_alloc_coherent(&dev->pdev->dev, - size, &t, GFP_KERNEL); - if (!buf->u.direct.buf) - return -ENOMEM; - - buf->u.direct.map = t; - - while (t & ((1 << buf->page_shift) - 1)) { - --buf->page_shift; - buf->npages *= 2; - } - - memset(buf->u.direct.buf, 0, size); - } else { - int i; - - buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; - buf->npages = buf->nbufs; - buf->page_shift = PAGE_SHIFT; - buf->u.page_list = kzalloc(buf->nbufs * sizeof *buf->u.page_list, - GFP_KERNEL); - if (!buf->u.page_list) - return -ENOMEM; - - for (i = 0; i < buf->nbufs; ++i) { - buf->u.page_list[i].buf = - dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, - &t, GFP_KERNEL); - if (!buf->u.page_list[i].buf) - goto err_free; - - buf->u.page_list[i].map = t; - - memset(buf->u.page_list[i].buf, 0, PAGE_SIZE); - } - } - - return 0; - -err_free: - mlx4_buf_free(dev, size, buf); - - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(mlx4_buf_alloc); - -void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf) -{ - int i; - - if (buf->nbufs == 1) - dma_free_coherent(&dev->pdev->dev, size, buf->u.direct.buf, - buf->u.direct.map); - else { - for (i = 0; i < buf->nbufs; ++i) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - buf->u.page_list[i].buf, - buf->u.page_list[i].map); - kfree(buf->u.page_list); - } -} -EXPORT_SYMBOL_GPL(mlx4_buf_free); diff --git a/trunk/drivers/net/mlx4/catas.c b/trunk/drivers/net/mlx4/catas.c deleted file mode 100644 index 1bb088aeaf71..000000000000 --- a/trunk/drivers/net/mlx4/catas.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, 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 "mlx4.h" - -void mlx4_handle_catas_err(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - int i; - - mlx4_err(dev, "Catastrophic error detected:\n"); - for (i = 0; i < priv->fw.catas_size; ++i) - mlx4_err(dev, " buf[%02x]: %08x\n", - i, swab32(readl(priv->catas_err.map + i))); - - mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0); -} - -void mlx4_map_catas_buf(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - unsigned long addr; - - addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) + - priv->fw.catas_offset; - - priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4); - if (!priv->catas_err.map) - mlx4_warn(dev, "Failed to map catastrophic error buffer at 0x%lx\n", - addr); - -} - -void mlx4_unmap_catas_buf(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - if (priv->catas_err.map) - iounmap(priv->catas_err.map); -} diff --git a/trunk/drivers/net/mlx4/cmd.c b/trunk/drivers/net/mlx4/cmd.c deleted file mode 100644 index c1f81a993f5d..000000000000 --- a/trunk/drivers/net/mlx4/cmd.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, 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 "mlx4.h" - -#define CMD_POLL_TOKEN 0xffff - -enum { - /* command completed successfully: */ - CMD_STAT_OK = 0x00, - /* Internal error (such as a bus error) occurred while processing command: */ - CMD_STAT_INTERNAL_ERR = 0x01, - /* Operation/command not supported or opcode modifier not supported: */ - CMD_STAT_BAD_OP = 0x02, - /* Parameter not supported or parameter out of range: */ - CMD_STAT_BAD_PARAM = 0x03, - /* System not enabled or bad system state: */ - CMD_STAT_BAD_SYS_STATE = 0x04, - /* Attempt to access reserved or unallocaterd resource: */ - CMD_STAT_BAD_RESOURCE = 0x05, - /* Requested resource is currently executing a command, or is otherwise busy: */ - CMD_STAT_RESOURCE_BUSY = 0x06, - /* Required capability exceeds device limits: */ - CMD_STAT_EXCEED_LIM = 0x08, - /* Resource is not in the appropriate state or ownership: */ - CMD_STAT_BAD_RES_STATE = 0x09, - /* Index out of range: */ - CMD_STAT_BAD_INDEX = 0x0a, - /* FW image corrupted: */ - CMD_STAT_BAD_NVMEM = 0x0b, - /* Attempt to modify a QP/EE which is not in the presumed state: */ - CMD_STAT_BAD_QP_STATE = 0x10, - /* Bad segment parameters (Address/Size): */ - CMD_STAT_BAD_SEG_PARAM = 0x20, - /* Memory Region has Memory Windows bound to: */ - CMD_STAT_REG_BOUND = 0x21, - /* HCA local attached memory not present: */ - CMD_STAT_LAM_NOT_PRE = 0x22, - /* Bad management packet (silently discarded): */ - CMD_STAT_BAD_PKT = 0x30, - /* More outstanding CQEs in CQ than new CQ size: */ - CMD_STAT_BAD_SIZE = 0x40 -}; - -enum { - HCR_IN_PARAM_OFFSET = 0x00, - HCR_IN_MODIFIER_OFFSET = 0x08, - HCR_OUT_PARAM_OFFSET = 0x0c, - HCR_TOKEN_OFFSET = 0x14, - HCR_STATUS_OFFSET = 0x18, - - HCR_OPMOD_SHIFT = 12, - HCR_T_BIT = 21, - HCR_E_BIT = 22, - HCR_GO_BIT = 23 -}; - -enum { - GO_BIT_TIMEOUT = 10000 -}; - -struct mlx4_cmd_context { - struct completion done; - int result; - int next; - u64 out_param; - u16 token; -}; - -static int mlx4_status_to_errno(u8 status) { - static const int trans_table[] = { - [CMD_STAT_INTERNAL_ERR] = -EIO, - [CMD_STAT_BAD_OP] = -EPERM, - [CMD_STAT_BAD_PARAM] = -EINVAL, - [CMD_STAT_BAD_SYS_STATE] = -ENXIO, - [CMD_STAT_BAD_RESOURCE] = -EBADF, - [CMD_STAT_RESOURCE_BUSY] = -EBUSY, - [CMD_STAT_EXCEED_LIM] = -ENOMEM, - [CMD_STAT_BAD_RES_STATE] = -EBADF, - [CMD_STAT_BAD_INDEX] = -EBADF, - [CMD_STAT_BAD_NVMEM] = -EFAULT, - [CMD_STAT_BAD_QP_STATE] = -EINVAL, - [CMD_STAT_BAD_SEG_PARAM] = -EFAULT, - [CMD_STAT_REG_BOUND] = -EBUSY, - [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, - [CMD_STAT_BAD_PKT] = -EINVAL, - [CMD_STAT_BAD_SIZE] = -ENOMEM, - }; - - if (status >= ARRAY_SIZE(trans_table) || - (status != CMD_STAT_OK && trans_table[status] == 0)) - return -EIO; - - return trans_table[status]; -} - -static int cmd_pending(struct mlx4_dev *dev) -{ - u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); - - return (status & swab32(1 << HCR_GO_BIT)) || - (mlx4_priv(dev)->cmd.toggle == - !!(status & swab32(1 << HCR_T_BIT))); -} - -static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, - u32 in_modifier, u8 op_modifier, u16 op, u16 token, - int event) -{ - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - u32 __iomem *hcr = cmd->hcr; - int ret = -EAGAIN; - unsigned long end; - - mutex_lock(&cmd->hcr_mutex); - - end = jiffies; - if (event) - end += HZ * 10; - - while (cmd_pending(dev)) { - if (time_after_eq(jiffies, end)) - goto out; - cond_resched(); - } - - /* - * We use writel (instead of something like memcpy_toio) - * because writes of less than 32 bits to the HCR don't work - * (and some architectures such as ia64 implement memcpy_toio - * in terms of writeb). - */ - __raw_writel((__force u32) cpu_to_be32(in_param >> 32), hcr + 0); - __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1); - __raw_writel((__force u32) cpu_to_be32(in_modifier), hcr + 2); - __raw_writel((__force u32) cpu_to_be32(out_param >> 32), hcr + 3); - __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4); - __raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5); - - /* __raw_writel may not order writes. */ - wmb(); - - __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | - (cmd->toggle << HCR_T_BIT) | - (event ? (1 << HCR_E_BIT) : 0) | - (op_modifier << HCR_OPMOD_SHIFT) | - op), hcr + 6); - cmd->toggle = cmd->toggle ^ 1; - - ret = 0; - -out: - mutex_unlock(&cmd->hcr_mutex); - return ret; -} - -static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - void __iomem *hcr = priv->cmd.hcr; - int err = 0; - unsigned long end; - - down(&priv->cmd.poll_sem); - - err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, - in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); - if (err) - goto out; - - end = msecs_to_jiffies(timeout) + jiffies; - while (cmd_pending(dev) && time_before(jiffies, end)) - cond_resched(); - - if (cmd_pending(dev)) { - err = -ETIMEDOUT; - goto out; - } - - if (out_is_imm) - *out_param = - (u64) be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 | - (u64) be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4)); - - err = mlx4_status_to_errno(be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24); - -out: - up(&priv->cmd.poll_sem); - return err; -} - -void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_context *context = - &priv->cmd.context[token & priv->cmd.token_mask]; - - /* previously timed out command completing at long last */ - if (token != context->token) - return; - - context->result = mlx4_status_to_errno(status); - context->out_param = out_param; - - context->token += priv->cmd.token_mask + 1; - - complete(&context->done); -} - -static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - struct mlx4_cmd_context *context; - int err = 0; - - down(&cmd->event_sem); - - spin_lock(&cmd->context_lock); - BUG_ON(cmd->free_head < 0); - context = &cmd->context[cmd->free_head]; - cmd->free_head = context->next; - spin_unlock(&cmd->context_lock); - - init_completion(&context->done); - - mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, - in_modifier, op_modifier, op, context->token, 1); - - if (!wait_for_completion_timeout(&context->done, msecs_to_jiffies(timeout))) { - err = -EBUSY; - goto out; - } - - err = context->result; - if (err) - goto out; - - if (out_is_imm) - *out_param = context->out_param; - -out: - spin_lock(&cmd->context_lock); - context->next = cmd->free_head; - cmd->free_head = context - cmd->context; - spin_unlock(&cmd->context_lock); - - up(&cmd->event_sem); - return err; -} - -int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - if (mlx4_priv(dev)->cmd.use_events) - return mlx4_cmd_wait(dev, in_param, out_param, out_is_imm, - in_modifier, op_modifier, op, timeout); - else - return mlx4_cmd_poll(dev, in_param, out_param, out_is_imm, - in_modifier, op_modifier, op, timeout); -} -EXPORT_SYMBOL_GPL(__mlx4_cmd); - -int mlx4_cmd_init(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mutex_init(&priv->cmd.hcr_mutex); - sema_init(&priv->cmd.poll_sem, 1); - priv->cmd.use_events = 0; - priv->cmd.toggle = 1; - - priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE, - MLX4_HCR_SIZE); - if (!priv->cmd.hcr) { - mlx4_err(dev, "Couldn't map command register."); - return -ENOMEM; - } - - priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, - MLX4_MAILBOX_SIZE, - MLX4_MAILBOX_SIZE, 0); - if (!priv->cmd.pool) { - iounmap(priv->cmd.hcr); - return -ENOMEM; - } - - return 0; -} - -void mlx4_cmd_cleanup(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - pci_pool_destroy(priv->cmd.pool); - iounmap(priv->cmd.hcr); -} - -/* - * Switch to using events to issue FW commands (can only be called - * after event queue for command events has been initialized). - */ -int mlx4_cmd_use_events(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - priv->cmd.context = kmalloc(priv->cmd.max_cmds * - sizeof (struct mlx4_cmd_context), - GFP_KERNEL); - if (!priv->cmd.context) - return -ENOMEM; - - for (i = 0; i < priv->cmd.max_cmds; ++i) { - priv->cmd.context[i].token = i; - priv->cmd.context[i].next = i + 1; - } - - priv->cmd.context[priv->cmd.max_cmds - 1].next = -1; - priv->cmd.free_head = 0; - - sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds); - spin_lock_init(&priv->cmd.context_lock); - - for (priv->cmd.token_mask = 1; - priv->cmd.token_mask < priv->cmd.max_cmds; - priv->cmd.token_mask <<= 1) - ; /* nothing */ - --priv->cmd.token_mask; - - priv->cmd.use_events = 1; - - down(&priv->cmd.poll_sem); - - return 0; -} - -/* - * Switch back to polling (used when shutting down the device) - */ -void mlx4_cmd_use_polling(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - priv->cmd.use_events = 0; - - for (i = 0; i < priv->cmd.max_cmds; ++i) - down(&priv->cmd.event_sem); - - kfree(priv->cmd.context); - - up(&priv->cmd.poll_sem); -} - -struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) -{ - struct mlx4_cmd_mailbox *mailbox; - - mailbox = kmalloc(sizeof *mailbox, GFP_KERNEL); - if (!mailbox) - return ERR_PTR(-ENOMEM); - - mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL, - &mailbox->dma); - if (!mailbox->buf) { - kfree(mailbox); - return ERR_PTR(-ENOMEM); - } - - return mailbox; -} -EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox); - -void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox) -{ - if (!mailbox) - return; - - pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma); - kfree(mailbox); -} -EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox); diff --git a/trunk/drivers/net/mlx4/cq.c b/trunk/drivers/net/mlx4/cq.c deleted file mode 100644 index 437d78ad0912..000000000000 --- a/trunk/drivers/net/mlx4/cq.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, 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 "mlx4.h" -#include "icm.h" - -struct mlx4_cq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - __be32 logsize_usrpage; - u8 reserved2; - u8 cq_period; - u8 reserved3; - u8 cq_max_count; - u8 reserved4[3]; - u8 comp_eqn; - u8 log_page_size; - u8 reserved5[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 last_notified_index; - __be32 solicit_producer_index; - __be32 consumer_index; - __be32 producer_index; - u8 reserved6[2]; - __be64 db_rec_addr; -}; - -#define MLX4_CQ_STATUS_OK ( 0 << 28) -#define MLX4_CQ_STATUS_OVERFLOW ( 9 << 28) -#define MLX4_CQ_STATUS_WRITE_FAIL (10 << 28) -#define MLX4_CQ_FLAG_CC ( 1 << 18) -#define MLX4_CQ_FLAG_OI ( 1 << 17) -#define MLX4_CQ_STATE_ARMED ( 9 << 8) -#define MLX4_CQ_STATE_ARMED_SOL ( 6 << 8) -#define MLX4_EQ_STATE_FIRED (10 << 8) - -void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) -{ - struct mlx4_cq *cq; - - cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, - cqn & (dev->caps.num_cqs - 1)); - if (!cq) { - mlx4_warn(dev, "Completion event for bogus CQ %08x\n", cqn); - return; - } - - ++cq->arm_sn; - - cq->comp(cq); -} - -void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) -{ - struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; - struct mlx4_cq *cq; - - spin_lock(&cq_table->lock); - - cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1)); - if (cq) - atomic_inc(&cq->refcount); - - spin_unlock(&cq_table->lock); - - if (!cq) { - mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn); - return; - } - - cq->event(cq, event_type); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); -} - -static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int cq_num) -{ - return mlx4_cmd(dev, mailbox->dma, cq_num, 0, MLX4_CMD_SW2HW_CQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int cq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, cq_num, - mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ, - MLX4_CMD_TIME_CLASS_A); -} - -int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, - struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_cq_context *cq_context; - u64 mtt_addr; - int err; - - cq->cqn = mlx4_bitmap_alloc(&cq_table->bitmap); - if (cq->cqn == -1) - return -ENOMEM; - - err = mlx4_table_get(dev, &cq_table->table, cq->cqn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &cq_table->cmpt_table, cq->cqn); - if (err) - goto err_put; - - spin_lock_irq(&cq_table->lock); - err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); - spin_unlock_irq(&cq_table->lock); - if (err) - goto err_cmpt_put; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_radix; - } - - cq_context = mailbox->buf; - memset(cq_context, 0, sizeof *cq_context); - - cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index); - cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn; - cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, mtt); - cq_context->mtt_base_addr_h = mtt_addr >> 32; - cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - cq_context->db_rec_addr = cpu_to_be64(db_rec); - - err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - goto err_radix; - - cq->cons_index = 0; - cq->arm_sn = 1; - cq->uar = uar; - atomic_set(&cq->refcount, 1); - init_completion(&cq->free); - - return 0; - -err_radix: - spin_lock_irq(&cq_table->lock); - radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock_irq(&cq_table->lock); - -err_cmpt_put: - mlx4_table_put(dev, &cq_table->cmpt_table, cq->cqn); - -err_put: - mlx4_table_put(dev, &cq_table->table, cq->cqn); - -err_out: - mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_cq_alloc); - -void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - int err; - - err = mlx4_HW2SW_CQ(dev, NULL, cq->cqn); - if (err) - mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn); - - synchronize_irq(priv->eq_table.eq[MLX4_EQ_COMP].irq); - - spin_lock_irq(&cq_table->lock); - radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock_irq(&cq_table->lock); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); - wait_for_completion(&cq->free); - - mlx4_table_put(dev, &cq_table->table, cq->cqn); - mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); -} -EXPORT_SYMBOL_GPL(mlx4_cq_free); - -int __devinit mlx4_init_cq_table(struct mlx4_dev *dev) -{ - struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; - int err; - - spin_lock_init(&cq_table->lock); - INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC); - - err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs, - dev->caps.num_cqs - 1, dev->caps.reserved_cqs); - if (err) - return err; - - return 0; -} - -void mlx4_cleanup_cq_table(struct mlx4_dev *dev) -{ - /* Nothing to do to clean up radix_tree */ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->cq_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/eq.c b/trunk/drivers/net/mlx4/eq.c deleted file mode 100644 index acf1c801a1b8..000000000000 --- a/trunk/drivers/net/mlx4/eq.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "fw.h" - -enum { - MLX4_NUM_ASYNC_EQE = 0x100, - MLX4_NUM_SPARE_EQE = 0x80, - MLX4_EQ_ENTRY_SIZE = 0x20 -}; - -/* - * Must be packed because start is 64 bits but only aligned to 32 bits. - */ -struct mlx4_eq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - u8 log_eq_size; - u8 reserved2[4]; - u8 eq_period; - u8 reserved3; - u8 eq_max_count; - u8 reserved4[3]; - u8 intr; - u8 log_page_size; - u8 reserved5[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - u32 reserved6[2]; - __be32 consumer_index; - __be32 producer_index; - u32 reserved7[4]; -}; - -#define MLX4_EQ_STATUS_OK ( 0 << 28) -#define MLX4_EQ_STATUS_WRITE_FAIL (10 << 28) -#define MLX4_EQ_OWNER_SW ( 0 << 24) -#define MLX4_EQ_OWNER_HW ( 1 << 24) -#define MLX4_EQ_FLAG_EC ( 1 << 18) -#define MLX4_EQ_FLAG_OI ( 1 << 17) -#define MLX4_EQ_STATE_ARMED ( 9 << 8) -#define MLX4_EQ_STATE_FIRED (10 << 8) -#define MLX4_EQ_STATE_ALWAYS_ARMED (11 << 8) - -#define MLX4_ASYNC_EVENT_MASK ((1ull << MLX4_EVENT_TYPE_PATH_MIG) | \ - (1ull << MLX4_EVENT_TYPE_COMM_EST) | \ - (1ull << MLX4_EVENT_TYPE_SQ_DRAINED) | \ - (1ull << MLX4_EVENT_TYPE_CQ_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_WQ_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_EEC_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \ - (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \ - (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ - (1ull << MLX4_EVENT_TYPE_CMD)) -#define MLX4_CATAS_EVENT_MASK (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) - -struct mlx4_eqe { - u8 reserved1; - u8 type; - u8 reserved2; - u8 subtype; - union { - u32 raw[6]; - struct { - __be32 cqn; - } __attribute__((packed)) comp; - struct { - u16 reserved1; - __be16 token; - u32 reserved2; - u8 reserved3[3]; - u8 status; - __be64 out_param; - } __attribute__((packed)) cmd; - struct { - __be32 qpn; - } __attribute__((packed)) qp; - struct { - __be32 srqn; - } __attribute__((packed)) srq; - struct { - __be32 cqn; - u32 reserved1; - u8 reserved2[3]; - u8 syndrome; - } __attribute__((packed)) cq_err; - struct { - u32 reserved1[2]; - __be32 port; - } __attribute__((packed)) port_change; - } event; - u8 reserved3[3]; - u8 owner; -} __attribute__((packed)); - -static void eq_set_ci(struct mlx4_eq *eq, int req_not) -{ - __raw_writel((__force u32) cpu_to_be32((eq->cons_index & 0xffffff) | - req_not << 31), - eq->doorbell); - /* We still want ordering, just not swabbing, so add a barrier */ - mb(); -} - -static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry) -{ - unsigned long off = (entry & (eq->nent - 1)) * MLX4_EQ_ENTRY_SIZE; - return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE; -} - -static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq) -{ - struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index); - return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; -} - -static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) -{ - struct mlx4_eqe *eqe; - int cqn; - int eqes_found = 0; - int set_ci = 0; - - while ((eqe = next_eqe_sw(eq))) { - /* - * Make sure we read EQ entry contents after we've - * checked the ownership bit. - */ - rmb(); - - switch (eqe->type) { - case MLX4_EVENT_TYPE_COMP: - cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff; - mlx4_cq_completion(dev, cqn); - break; - - case MLX4_EVENT_TYPE_PATH_MIG: - case MLX4_EVENT_TYPE_COMM_EST: - case MLX4_EVENT_TYPE_SQ_DRAINED: - case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE: - case MLX4_EVENT_TYPE_WQ_CATAS_ERROR: - case MLX4_EVENT_TYPE_PATH_MIG_FAILED: - case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR: - mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff, - eqe->type); - break; - - case MLX4_EVENT_TYPE_SRQ_LIMIT: - case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff, - eqe->type); - break; - - case MLX4_EVENT_TYPE_CMD: - mlx4_cmd_event(dev, - be16_to_cpu(eqe->event.cmd.token), - eqe->event.cmd.status, - be64_to_cpu(eqe->event.cmd.out_param)); - break; - - case MLX4_EVENT_TYPE_PORT_CHANGE: - mlx4_dispatch_event(dev, eqe->type, eqe->subtype, - be32_to_cpu(eqe->event.port_change.port) >> 28); - break; - - case MLX4_EVENT_TYPE_CQ_ERROR: - mlx4_warn(dev, "CQ %s on CQN %06x\n", - eqe->event.cq_err.syndrome == 1 ? - "overrun" : "access violation", - be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff); - mlx4_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn), - eqe->type); - break; - - case MLX4_EVENT_TYPE_EQ_OVERFLOW: - mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn); - break; - - case MLX4_EVENT_TYPE_EEC_CATAS_ERROR: - case MLX4_EVENT_TYPE_ECC_DETECT: - default: - mlx4_warn(dev, "Unhandled event %02x(%02x) on EQ %d at index %u\n", - eqe->type, eqe->subtype, eq->eqn, eq->cons_index); - break; - }; - - ++eq->cons_index; - eqes_found = 1; - ++set_ci; - - /* - * The HCA will think the queue has overflowed if we - * don't tell it we've been processing events. We - * create our EQs with MLX4_NUM_SPARE_EQE extra - * entries, so we must update our consumer index at - * least that often. - */ - if (unlikely(set_ci >= MLX4_NUM_SPARE_EQE)) { - /* - * Conditional on hca_type is OK here because - * this is a rare case, not the fast path. - */ - eq_set_ci(eq, 0); - set_ci = 0; - } - } - - eq_set_ci(eq, 1); - - return eqes_found; -} - -static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr) -{ - struct mlx4_dev *dev = dev_ptr; - struct mlx4_priv *priv = mlx4_priv(dev); - int work = 0; - int i; - - writel(priv->eq_table.clr_mask, priv->eq_table.clr_int); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]); - - return IRQ_RETVAL(work); -} - -static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr) -{ - struct mlx4_eq *eq = eq_ptr; - struct mlx4_dev *dev = eq->dev; - - mlx4_eq_int(dev, eq); - - /* MSI-X vectors always belong to us */ - return IRQ_HANDLED; -} - -static irqreturn_t mlx4_catas_interrupt(int irq, void *dev_ptr) -{ - mlx4_handle_catas_err(dev_ptr); - - /* MSI-X vectors always belong to us */ - return IRQ_HANDLED; -} - -static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, - int eq_num) -{ - return mlx4_cmd(dev, event_mask, (unmap << 31) | eq_num, - 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B); -} - -static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int eq_num) -{ - return mlx4_cmd(dev, mailbox->dma, eq_num, 0, MLX4_CMD_SW2HW_EQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int eq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num, 0, MLX4_CMD_HW2SW_EQ, - MLX4_CMD_TIME_CLASS_A); -} - -static void __devinit __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, - struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int index; - - index = eq->eqn / 4 - dev->caps.reserved_eqs / 4; - - if (!priv->eq_table.uar_map[index]) { - priv->eq_table.uar_map[index] = - ioremap(pci_resource_start(dev->pdev, 2) + - ((eq->eqn / 4) << PAGE_SHIFT), - PAGE_SIZE); - if (!priv->eq_table.uar_map[index]) { - mlx4_err(dev, "Couldn't map EQ doorbell for EQN 0x%06x\n", - eq->eqn); - return NULL; - } - } - - return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); -} - -static int __devinit mlx4_create_eq(struct mlx4_dev *dev, int nent, - u8 intr, struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_eq_context *eq_context; - int npages; - u64 *dma_list = NULL; - dma_addr_t t; - u64 mtt_addr; - int err = -ENOMEM; - int i; - - eq->dev = dev; - eq->nent = roundup_pow_of_two(max(nent, 2)); - npages = PAGE_ALIGN(eq->nent * MLX4_EQ_ENTRY_SIZE) / PAGE_SIZE; - - eq->page_list = kmalloc(npages * sizeof *eq->page_list, - GFP_KERNEL); - if (!eq->page_list) - goto err_out; - - for (i = 0; i < npages; ++i) - eq->page_list[i].buf = NULL; - - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); - if (!dma_list) - goto err_out_free; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - goto err_out_free; - eq_context = mailbox->buf; - - for (i = 0; i < npages; ++i) { - eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev, - PAGE_SIZE, &t, GFP_KERNEL); - if (!eq->page_list[i].buf) - goto err_out_free_pages; - - dma_list[i] = t; - eq->page_list[i].map = t; - - memset(eq->page_list[i].buf, 0, PAGE_SIZE); - } - - eq->eqn = mlx4_bitmap_alloc(&priv->eq_table.bitmap); - if (eq->eqn == -1) - goto err_out_free_pages; - - eq->doorbell = mlx4_get_eq_uar(dev, eq); - if (!eq->doorbell) { - err = -ENOMEM; - goto err_out_free_eq; - } - - err = mlx4_mtt_init(dev, npages, PAGE_SHIFT, &eq->mtt); - if (err) - goto err_out_free_eq; - - err = mlx4_write_mtt(dev, &eq->mtt, 0, npages, dma_list); - if (err) - goto err_out_free_mtt; - - memset(eq_context, 0, sizeof *eq_context); - eq_context->flags = cpu_to_be32(MLX4_EQ_STATUS_OK | - MLX4_EQ_STATE_ARMED); - eq_context->log_eq_size = ilog2(eq->nent); - eq_context->intr = intr; - eq_context->log_page_size = PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, &eq->mtt); - eq_context->mtt_base_addr_h = mtt_addr >> 32; - eq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - - err = mlx4_SW2HW_EQ(dev, mailbox, eq->eqn); - if (err) { - mlx4_warn(dev, "SW2HW_EQ failed (%d)\n", err); - goto err_out_free_mtt; - } - - kfree(dma_list); - mlx4_free_cmd_mailbox(dev, mailbox); - - eq->cons_index = 0; - - return err; - -err_out_free_mtt: - mlx4_mtt_cleanup(dev, &eq->mtt); - -err_out_free_eq: - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); - -err_out_free_pages: - for (i = 0; i < npages; ++i) - if (eq->page_list[i].buf) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - eq->page_list[i].buf, - eq->page_list[i].map); - - mlx4_free_cmd_mailbox(dev, mailbox); - -err_out_free: - kfree(eq->page_list); - kfree(dma_list); - -err_out: - return err; -} - -static void mlx4_free_eq(struct mlx4_dev *dev, - struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - int err; - int npages = PAGE_ALIGN(MLX4_EQ_ENTRY_SIZE * eq->nent) / PAGE_SIZE; - int i; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return; - - err = mlx4_HW2SW_EQ(dev, mailbox, eq->eqn); - if (err) - mlx4_warn(dev, "HW2SW_EQ failed (%d)\n", err); - - if (0) { - mlx4_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn); - for (i = 0; i < sizeof (struct mlx4_eq_context) / 4; ++i) { - if (i % 4 == 0) - printk("[%02x] ", i * 4); - printk(" %08x", be32_to_cpup(mailbox->buf + i * 4)); - if ((i + 1) % 4 == 0) - printk("\n"); - } - } - - mlx4_mtt_cleanup(dev, &eq->mtt); - for (i = 0; i < npages; ++i) - pci_free_consistent(dev->pdev, PAGE_SIZE, - eq->page_list[i].buf, - eq->page_list[i].map); - - kfree(eq->page_list); - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); - mlx4_free_cmd_mailbox(dev, mailbox); -} - -static void mlx4_free_irqs(struct mlx4_dev *dev) -{ - struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table; - int i; - - if (eq_table->have_irq) - free_irq(dev->pdev->irq, dev); - for (i = 0; i < MLX4_NUM_EQ; ++i) - if (eq_table->eq[i].have_irq) - free_irq(eq_table->eq[i].irq, eq_table->eq + i); -} - -static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - priv->clr_base = ioremap(pci_resource_start(dev->pdev, priv->fw.clr_int_bar) + - priv->fw.clr_int_base, MLX4_CLR_INT_SIZE); - if (!priv->clr_base) { - mlx4_err(dev, "Couldn't map interrupt clear register, aborting.\n"); - return -ENOMEM; - } - - return 0; -} - -static void mlx4_unmap_clr_int(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - iounmap(priv->clr_base); -} - -int __devinit mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int ret; - - /* - * We assume that mapping one page is enough for the whole EQ - * context table. This is fine with all current HCAs, because - * we only use 32 EQs and each EQ uses 64 bytes of context - * memory, or 1 KB total. - */ - priv->eq_table.icm_virt = icm_virt; - priv->eq_table.icm_page = alloc_page(GFP_HIGHUSER); - if (!priv->eq_table.icm_page) - return -ENOMEM; - priv->eq_table.icm_dma = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(priv->eq_table.icm_dma)) { - __free_page(priv->eq_table.icm_page); - return -ENOMEM; - } - - ret = mlx4_MAP_ICM_page(dev, priv->eq_table.icm_dma, icm_virt); - if (ret) { - pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->eq_table.icm_page); - } - - return ret; -} - -void mlx4_unmap_eq_icm(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mlx4_UNMAP_ICM(dev, priv->eq_table.icm_virt, 1); - pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->eq_table.icm_page); -} - -int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - int i; - - err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs, - dev->caps.num_eqs - 1, dev->caps.reserved_eqs); - if (err) - return err; - - for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i) - priv->eq_table.uar_map[i] = NULL; - - err = mlx4_map_clr_int(dev); - if (err) - goto err_out_free; - - priv->eq_table.clr_mask = - swab32(1 << (priv->eq_table.inta_pin & 31)); - priv->eq_table.clr_int = priv->clr_base + - (priv->eq_table.inta_pin < 32 ? 4 : 0); - - err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE, - (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_COMP : 0, - &priv->eq_table.eq[MLX4_EQ_COMP]); - if (err) - goto err_out_unmap; - - err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE, - (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_ASYNC : 0, - &priv->eq_table.eq[MLX4_EQ_ASYNC]); - if (err) - goto err_out_comp; - - if (dev->flags & MLX4_FLAG_MSI_X) { - static const char *eq_name[] = { - [MLX4_EQ_COMP] = DRV_NAME " (comp)", - [MLX4_EQ_ASYNC] = DRV_NAME " (async)", - [MLX4_EQ_CATAS] = DRV_NAME " (catas)" - }; - - err = mlx4_create_eq(dev, 1, MLX4_EQ_CATAS, - &priv->eq_table.eq[MLX4_EQ_CATAS]); - if (err) - goto err_out_async; - - for (i = 0; i < MLX4_EQ_CATAS; ++i) { - err = request_irq(priv->eq_table.eq[i].irq, - mlx4_msi_x_interrupt, - 0, eq_name[i], priv->eq_table.eq + i); - if (err) - goto err_out_catas; - - priv->eq_table.eq[i].have_irq = 1; - } - - err = request_irq(priv->eq_table.eq[MLX4_EQ_CATAS].irq, - mlx4_catas_interrupt, 0, - eq_name[MLX4_EQ_CATAS], dev); - if (err) - goto err_out_catas; - - priv->eq_table.eq[MLX4_EQ_CATAS].have_irq = 1; - } else { - err = request_irq(dev->pdev->irq, mlx4_interrupt, - SA_SHIRQ, DRV_NAME, dev); - if (err) - goto err_out_async; - - priv->eq_table.have_irq = 1; - } - - err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); - if (err) - mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n", - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - eq_set_ci(&priv->eq_table.eq[i], 1); - - if (dev->flags & MLX4_FLAG_MSI_X) { - err = mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 0, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - if (err) - mlx4_warn(dev, "MAP_EQ for catas EQ %d failed (%d)\n", - priv->eq_table.eq[MLX4_EQ_CATAS].eqn, err); - } - - return 0; - -err_out_catas: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); - -err_out_async: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]); - -err_out_comp: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_COMP]); - -err_out_unmap: - mlx4_unmap_clr_int(dev); - mlx4_free_irqs(dev); - -err_out_free: - mlx4_bitmap_cleanup(&priv->eq_table.bitmap); - return err; -} - -void mlx4_cleanup_eq_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 1, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - - mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1, - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); - - mlx4_free_irqs(dev); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - mlx4_free_eq(dev, &priv->eq_table.eq[i]); - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); - - mlx4_unmap_clr_int(dev); - - for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i) - if (priv->eq_table.uar_map[i]) - iounmap(priv->eq_table.uar_map[i]); - - mlx4_bitmap_cleanup(&priv->eq_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/fw.c b/trunk/drivers/net/mlx4/fw.c deleted file mode 100644 index c42717313663..000000000000 --- a/trunk/drivers/net/mlx4/fw.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, 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 "fw.h" -#include "icm.h" - -extern void __buggy_use_of_MLX4_GET(void); -extern void __buggy_use_of_MLX4_PUT(void); - -#define MLX4_GET(dest, source, offset) \ - do { \ - void *__p = (char *) (source) + (offset); \ - switch (sizeof (dest)) { \ - case 1: (dest) = *(u8 *) __p; break; \ - case 2: (dest) = be16_to_cpup(__p); break; \ - case 4: (dest) = be32_to_cpup(__p); break; \ - case 8: (dest) = be64_to_cpup(__p); break; \ - default: __buggy_use_of_MLX4_GET(); \ - } \ - } while (0) - -#define MLX4_PUT(dest, source, offset) \ - do { \ - void *__d = ((char *) (dest) + (offset)); \ - switch (sizeof(source)) { \ - case 1: *(u8 *) __d = (source); break; \ - case 2: *(__be16 *) __d = cpu_to_be16(source); break; \ - case 4: *(__be32 *) __d = cpu_to_be32(source); break; \ - case 8: *(__be64 *) __d = cpu_to_be64(source); break; \ - default: __buggy_use_of_MLX4_PUT(); \ - } \ - } while (0) - -static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags) -{ - static const char *fname[] = { - [ 0] = "RC transport", - [ 1] = "UC transport", - [ 2] = "UD transport", - [ 3] = "SRC transport", - [ 4] = "reliable multicast", - [ 5] = "FCoIB support", - [ 6] = "SRQ support", - [ 7] = "IPoIB checksum offload", - [ 8] = "P_Key violation counter", - [ 9] = "Q_Key violation counter", - [10] = "VMM", - [16] = "MW support", - [17] = "APM support", - [18] = "Atomic ops support", - [19] = "Raw multicast support", - [20] = "Address vector port checking support", - [21] = "UD multicast support", - [24] = "Demand paging support", - [25] = "Router support" - }; - int i; - - mlx4_dbg(dev, "DEV_CAP flags:\n"); - for (i = 0; i < 32; ++i) - if (fname[i] && (flags & (1 << i))) - mlx4_dbg(dev, " %s\n", fname[i]); -} - -int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - u8 field; - u16 size; - u16 stat_rate; - int err; - -#define QUERY_DEV_CAP_OUT_SIZE 0x100 -#define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 -#define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11 -#define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12 -#define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13 -#define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14 -#define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15 -#define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16 -#define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17 -#define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19 -#define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a -#define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b -#define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d -#define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e -#define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f -#define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20 -#define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21 -#define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22 -#define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23 -#define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27 -#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 -#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b -#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f -#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33 -#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 -#define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 -#define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 -#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b -#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c -#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f -#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 -#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 -#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 -#define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b -#define QUERY_DEV_CAP_BF_OFFSET 0x4c -#define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d -#define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e -#define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f -#define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51 -#define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52 -#define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55 -#define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56 -#define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61 -#define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62 -#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 -#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 -#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 -#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 -#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 -#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 -#define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86 -#define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88 -#define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a -#define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c -#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e -#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90 -#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92 -#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x97 -#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 -#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, - MLX4_CMD_TIME_CLASS_A); - - if (err) - goto out; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); - dev_cap->reserved_qps = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET); - dev_cap->max_qps = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET); - dev_cap->reserved_srqs = 1 << (field >> 4); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET); - dev_cap->max_srqs = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET); - dev_cap->max_cq_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET); - dev_cap->reserved_cqs = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET); - dev_cap->max_cqs = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET); - dev_cap->max_mpts = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET); - dev_cap->reserved_eqs = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET); - dev_cap->max_eqs = 1 << (field & 0x7); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET); - dev_cap->reserved_mtts = 1 << (field >> 4); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET); - dev_cap->max_mrw_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET); - dev_cap->reserved_mrws = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET); - dev_cap->max_mtt_seg = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET); - dev_cap->max_requester_per_qp = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET); - dev_cap->max_responder_per_qp = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET); - dev_cap->max_rdma_global = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); - dev_cap->local_ca_ack_delay = field & 0x1f; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); - dev_cap->max_mtu = field >> 4; - dev_cap->max_port_width = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); - dev_cap->max_vl = field >> 4; - dev_cap->num_ports = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); - dev_cap->max_gids = 1 << (field & 0xf); - MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); - dev_cap->stat_rate_support = stat_rate; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); - dev_cap->max_pkeys = 1 << (field & 0xf); - MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); - dev_cap->reserved_uars = field >> 4; - MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET); - dev_cap->uar_size = 1 << ((field & 0x3f) + 20); - MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET); - dev_cap->min_page_sz = 1 << field; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET); - if (field & 0x80) { - MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET); - dev_cap->bf_reg_size = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET); - dev_cap->bf_regs_per_page = 1 << (field & 0x3f); - mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n", - dev_cap->bf_reg_size, dev_cap->bf_regs_per_page); - } else { - dev_cap->bf_reg_size = 0; - mlx4_dbg(dev, "BlueFlame not available\n"); - } - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET); - dev_cap->max_sq_sg = field; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET); - dev_cap->max_sq_desc_sz = size; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET); - dev_cap->max_qp_per_mcg = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET); - dev_cap->reserved_mgms = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET); - dev_cap->max_mcgs = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET); - dev_cap->reserved_pds = field >> 4; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); - dev_cap->max_pds = 1 << (field & 0x3f); - - MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); - dev_cap->rdmarc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET); - dev_cap->qpc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET); - dev_cap->aux_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET); - dev_cap->altc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET); - dev_cap->eqc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET); - dev_cap->cqc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET); - dev_cap->srq_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET); - dev_cap->cmpt_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET); - dev_cap->mtt_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET); - dev_cap->dmpt_entry_sz = size; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET); - dev_cap->max_srq_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET); - dev_cap->max_qp_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET); - dev_cap->resize_srq = field & 1; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET); - dev_cap->max_rq_sg = field; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); - dev_cap->max_rq_desc_sz = size; - - MLX4_GET(dev_cap->bmme_flags, outbox, - QUERY_DEV_CAP_BMME_FLAGS_OFFSET); - MLX4_GET(dev_cap->reserved_lkey, outbox, - QUERY_DEV_CAP_RSVD_LKEY_OFFSET); - MLX4_GET(dev_cap->max_icm_sz, outbox, - QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); - - if (dev_cap->bmme_flags & 1) - mlx4_dbg(dev, "Base MM extensions: yes " - "(flags %d, rsvd L_Key %08x)\n", - dev_cap->bmme_flags, dev_cap->reserved_lkey); - else - mlx4_dbg(dev, "Base MM extensions: no\n"); - - /* - * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then - * we can't use any EQs whose doorbell falls on that page, - * even if the EQ itself isn't reserved. - */ - dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, - dev_cap->reserved_eqs); - - mlx4_dbg(dev, "Max ICM size %lld MB\n", - (unsigned long long) dev_cap->max_icm_sz >> 20); - mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", - dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz); - mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", - dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz); - mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", - dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz); - mlx4_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", - dev_cap->max_eqs, dev_cap->reserved_eqs, dev_cap->eqc_entry_sz); - mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", - dev_cap->reserved_mrws, dev_cap->reserved_mtts); - mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", - dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars); - mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", - dev_cap->max_pds, dev_cap->reserved_mgms); - mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", - dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); - mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", - dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu, - dev_cap->max_port_width); - mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", - dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); - mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", - dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg); - - dump_dev_cap_flags(dev, dev_cap->flags); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_icm_iter iter; - __be64 *pages; - int lg; - int nent = 0; - int i; - int err = 0; - int ts = 0, tc = 0; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE); - pages = mailbox->buf; - - for (mlx4_icm_first(icm, &iter); - !mlx4_icm_last(&iter); - mlx4_icm_next(&iter)) { - /* - * We have to pass pages that are aligned to their - * size, so find the least significant 1 in the - * address or size and use that as our log2 size. - */ - lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1; - if (lg < MLX4_ICM_PAGE_SHIFT) { - mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n", - MLX4_ICM_PAGE_SIZE, - (unsigned long long) mlx4_icm_addr(&iter), - mlx4_icm_size(&iter)); - err = -EINVAL; - goto out; - } - - for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) { - if (virt != -1) { - pages[nent * 2] = cpu_to_be64(virt); - virt += 1 << lg; - } - - pages[nent * 2 + 1] = - cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) | - (lg - MLX4_ICM_PAGE_SHIFT)); - ts += 1 << (lg - 10); - ++tc; - - if (++nent == MLX4_MAILBOX_SIZE / 16) { - err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, - MLX4_CMD_TIME_CLASS_B); - if (err) - goto out; - nent = 0; - } - } - } - - if (nent) - err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, MLX4_CMD_TIME_CLASS_B); - if (err) - goto out; - - switch (op) { - case MLX4_CMD_MAP_FA: - mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW.\n", tc, ts); - break; - case MLX4_CMD_MAP_ICM_AUX: - mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux.\n", tc, ts); - break; - case MLX4_CMD_MAP_ICM: - mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM.\n", - tc, ts, (unsigned long long) virt - (ts << 10)); - break; - } - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1); -} - -int mlx4_UNMAP_FA(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, MLX4_CMD_TIME_CLASS_B); -} - - -int mlx4_RUN_FW(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, MLX4_CMD_TIME_CLASS_A); -} - -int mlx4_QUERY_FW(struct mlx4_dev *dev) -{ - struct mlx4_fw *fw = &mlx4_priv(dev)->fw; - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - int err = 0; - u64 fw_ver; - u8 lg; - -#define QUERY_FW_OUT_SIZE 0x100 -#define QUERY_FW_VER_OFFSET 0x00 -#define QUERY_FW_MAX_CMD_OFFSET 0x0f -#define QUERY_FW_ERR_START_OFFSET 0x30 -#define QUERY_FW_ERR_SIZE_OFFSET 0x38 -#define QUERY_FW_ERR_BAR_OFFSET 0x3c - -#define QUERY_FW_SIZE_OFFSET 0x00 -#define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 -#define QUERY_FW_CLR_INT_BAR_OFFSET 0x28 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW, - MLX4_CMD_TIME_CLASS_A); - if (err) - goto out; - - MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); - /* - * FW subminor version is at more signifant bits than minor - * version, so swap here. - */ - dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | - ((fw_ver & 0xffff0000ull) >> 16) | - ((fw_ver & 0x0000ffffull) << 16); - - MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); - cmd->max_cmds = 1 << lg; - - mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n", - (int) (dev->caps.fw_ver >> 32), - (int) (dev->caps.fw_ver >> 16) & 0xffff, - (int) dev->caps.fw_ver & 0xffff, - cmd->max_cmds); - - MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); - MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); - MLX4_GET(fw->catas_bar, outbox, QUERY_FW_ERR_BAR_OFFSET); - fw->catas_bar = (fw->catas_bar >> 6) * 2; - - mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n", - (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar); - - MLX4_GET(fw->fw_pages, outbox, QUERY_FW_SIZE_OFFSET); - MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); - MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET); - fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2; - - mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); - - /* - * Round up number of system pages needed in case - * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. - */ - fw->fw_pages = - ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> - (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); - - mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n", - (unsigned long long) fw->clr_int_base, fw->clr_int_bar); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -static void get_board_id(void *vsd, char *board_id) -{ - int i; - -#define VSD_OFFSET_SIG1 0x00 -#define VSD_OFFSET_SIG2 0xde -#define VSD_OFFSET_MLX_BOARD_ID 0xd0 -#define VSD_OFFSET_TS_BOARD_ID 0x20 - -#define VSD_SIGNATURE_TOPSPIN 0x5ad - - memset(board_id, 0, MLX4_BOARD_ID_LEN); - - if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN && - be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) { - strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN); - } else { - /* - * The board ID is a string but the firmware byte - * swaps each 4-byte word before passing it back to - * us. Therefore we need to swab it before printing. - */ - for (i = 0; i < 4; ++i) - ((u32 *) board_id)[i] = - swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4)); - } -} - -int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - int err; - -#define QUERY_ADAPTER_OUT_SIZE 0x100 -#define QUERY_ADAPTER_VENDOR_ID_OFFSET 0x00 -#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04 -#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 -#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 -#define QUERY_ADAPTER_VSD_OFFSET 0x20 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER, - MLX4_CMD_TIME_CLASS_A); - if (err) - goto out; - - MLX4_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET); - MLX4_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET); - MLX4_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET); - MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); - - get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4, - adapter->board_id); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) -{ - struct mlx4_cmd_mailbox *mailbox; - __be32 *inbox; - int err; - -#define INIT_HCA_IN_SIZE 0x200 -#define INIT_HCA_VERSION_OFFSET 0x000 -#define INIT_HCA_VERSION 2 -#define INIT_HCA_FLAGS_OFFSET 0x014 -#define INIT_HCA_QPC_OFFSET 0x020 -#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) -#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) -#define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28) -#define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) -#define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) -#define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) -#define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) -#define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) -#define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) -#define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) -#define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) -#define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) -#define INIT_HCA_MCAST_OFFSET 0x0c0 -#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) -#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) -#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) -#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) -#define INIT_HCA_TPT_OFFSET 0x0f0 -#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) -#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) -#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10) -#define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18) -#define INIT_HCA_UAR_OFFSET 0x120 -#define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a) -#define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b) - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - memset(inbox, 0, INIT_HCA_IN_SIZE); - - *((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION; - -#if defined(__LITTLE_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); -#elif defined(__BIG_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); -#else -#error Host endianness not defined -#endif - /* Check port for UD address vector: */ - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); - - /* QPC/EEC/CQC/EQC/RDMARC attributes */ - - MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET); - MLX4_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET); - MLX4_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET); - MLX4_PUT(inbox, param->altc_base, INIT_HCA_ALTC_BASE_OFFSET); - MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET); - MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); - MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); - - /* multicast attributes */ - - MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); - - /* TPT attributes */ - - MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET); - MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET); - MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET); - - /* UAR attributes */ - - MLX4_PUT(inbox, (u8) (PAGE_SHIFT - 12), INIT_HCA_UAR_PAGE_SZ_OFFSET); - MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); - - err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 1000); - - if (err) - mlx4_err(dev, "INIT_HCA returns %d\n", err); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *inbox; - int err; - u32 flags; - -#define INIT_PORT_IN_SIZE 256 -#define INIT_PORT_FLAGS_OFFSET 0x00 -#define INIT_PORT_FLAG_SIG (1 << 18) -#define INIT_PORT_FLAG_NG (1 << 17) -#define INIT_PORT_FLAG_G0 (1 << 16) -#define INIT_PORT_VL_SHIFT 4 -#define INIT_PORT_PORT_WIDTH_SHIFT 8 -#define INIT_PORT_MTU_OFFSET 0x04 -#define INIT_PORT_MAX_GID_OFFSET 0x06 -#define INIT_PORT_MAX_PKEY_OFFSET 0x0a -#define INIT_PORT_GUID0_OFFSET 0x10 -#define INIT_PORT_NODE_GUID_OFFSET 0x18 -#define INIT_PORT_SI_GUID_OFFSET 0x20 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - memset(inbox, 0, INIT_PORT_IN_SIZE); - - flags = 0; - flags |= param->set_guid0 ? INIT_PORT_FLAG_G0 : 0; - flags |= param->set_node_guid ? INIT_PORT_FLAG_NG : 0; - flags |= param->set_si_guid ? INIT_PORT_FLAG_SIG : 0; - flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT; - flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; - MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); - - MLX4_PUT(inbox, param->mtu, INIT_PORT_MTU_OFFSET); - MLX4_PUT(inbox, param->max_gid, INIT_PORT_MAX_GID_OFFSET); - MLX4_PUT(inbox, param->max_pkey, INIT_PORT_MAX_PKEY_OFFSET); - MLX4_PUT(inbox, param->guid0, INIT_PORT_GUID0_OFFSET); - MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET); - MLX4_PUT(inbox, param->si_guid, INIT_PORT_SI_GUID_OFFSET); - - err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A); - - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_INIT_PORT); - -int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port) -{ - return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000); -} -EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT); - -int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) -{ - return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000); -} - -int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) -{ - int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, - MLX4_CMD_SET_ICM_SIZE, - MLX4_CMD_TIME_CLASS_A); - if (ret) - return ret; - - /* - * Round up number of system pages needed in case - * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. - */ - *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> - (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); - - return 0; -} - -int mlx4_NOP(struct mlx4_dev *dev) -{ - /* Input modifier of 0x1f means "finish as soon as possible." */ - return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100); -} diff --git a/trunk/drivers/net/mlx4/fw.h b/trunk/drivers/net/mlx4/fw.h deleted file mode 100644 index 2616fa53d4d0..000000000000 --- a/trunk/drivers/net/mlx4/fw.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems. 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 MLX4_FW_H -#define MLX4_FW_H - -#include "mlx4.h" -#include "icm.h" - -struct mlx4_dev_cap { - int max_srq_sz; - int max_qp_sz; - int reserved_qps; - int max_qps; - int reserved_srqs; - int max_srqs; - int max_cq_sz; - int reserved_cqs; - int max_cqs; - int max_mpts; - int reserved_eqs; - int max_eqs; - int reserved_mtts; - int max_mrw_sz; - int reserved_mrws; - int max_mtt_seg; - int max_requester_per_qp; - int max_responder_per_qp; - int max_rdma_global; - int local_ca_ack_delay; - int max_mtu; - int max_port_width; - int max_vl; - int num_ports; - int max_gids; - u16 stat_rate_support; - int max_pkeys; - u32 flags; - int reserved_uars; - int uar_size; - int min_page_sz; - int bf_reg_size; - int bf_regs_per_page; - int max_sq_sg; - int max_sq_desc_sz; - int max_rq_sg; - int max_rq_desc_sz; - int max_qp_per_mcg; - int reserved_mgms; - int max_mcgs; - int reserved_pds; - int max_pds; - int qpc_entry_sz; - int rdmarc_entry_sz; - int altc_entry_sz; - int aux_entry_sz; - int srq_entry_sz; - int cqc_entry_sz; - int eqc_entry_sz; - int dmpt_entry_sz; - int cmpt_entry_sz; - int mtt_entry_sz; - int resize_srq; - u8 bmme_flags; - u32 reserved_lkey; - u64 max_icm_sz; -}; - -struct mlx4_adapter { - u32 vendor_id; - u32 device_id; - u32 revision_id; - char board_id[MLX4_BOARD_ID_LEN]; - u8 inta_pin; -}; - -struct mlx4_init_hca_param { - u64 qpc_base; - u64 rdmarc_base; - u64 auxc_base; - u64 altc_base; - u64 srqc_base; - u64 cqc_base; - u64 eqc_base; - u64 mc_base; - u64 dmpt_base; - u64 cmpt_base; - u64 mtt_base; - u16 log_mc_entry_sz; - u16 log_mc_hash_sz; - u8 log_num_qps; - u8 log_num_srqs; - u8 log_num_cqs; - u8 log_num_eqs; - u8 log_rd_per_qp; - u8 log_mc_table_sz; - u8 log_mpt_sz; - u8 log_uar_sz; -}; - -struct mlx4_init_ib_param { - int port_width; - int vl_cap; - int mtu_cap; - u16 gid_cap; - u16 pkey_cap; - int set_guid0; - u64 guid0; - int set_node_guid; - u64 node_guid; - int set_si_guid; - u64 si_guid; -}; - -struct mlx4_set_ib_param { - int set_si_guid; - int reset_qkey_viol; - u64 si_guid; - u32 cap_mask; -}; - -int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); -int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_FA(struct mlx4_dev *dev); -int mlx4_RUN_FW(struct mlx4_dev *dev); -int mlx4_QUERY_FW(struct mlx4_dev *dev); -int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter); -int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param); -int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic); -int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt); -int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages); -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); -int mlx4_NOP(struct mlx4_dev *dev); - -#endif /* MLX4_FW_H */ diff --git a/trunk/drivers/net/mlx4/icm.c b/trunk/drivers/net/mlx4/icm.c deleted file mode 100644 index e96feaed6ed4..000000000000 --- a/trunk/drivers/net/mlx4/icm.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "icm.h" -#include "fw.h" - -/* - * We allocate in as big chunks as we can, up to a maximum of 256 KB - * per chunk. - */ -enum { - MLX4_ICM_ALLOC_SIZE = 1 << 18, - MLX4_TABLE_CHUNK_SIZE = 1 << 18 -}; - -void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - struct mlx4_icm_chunk *chunk, *tmp; - int i; - - list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) { - if (chunk->nsg > 0) - pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - for (i = 0; i < chunk->npages; ++i) - __free_pages(chunk->mem[i].page, - get_order(chunk->mem[i].length)); - - kfree(chunk); - } - - kfree(icm); -} - -struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, - gfp_t gfp_mask) -{ - struct mlx4_icm *icm; - struct mlx4_icm_chunk *chunk = NULL; - int cur_order; - - icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); - if (!icm) - return icm; - - icm->refcount = 0; - INIT_LIST_HEAD(&icm->chunk_list); - - cur_order = get_order(MLX4_ICM_ALLOC_SIZE); - - while (npages > 0) { - if (!chunk) { - chunk = kmalloc(sizeof *chunk, - gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); - if (!chunk) - goto fail; - - chunk->npages = 0; - chunk->nsg = 0; - list_add_tail(&chunk->list, &icm->chunk_list); - } - - while (1 << cur_order > npages) - --cur_order; - - chunk->mem[chunk->npages].page = alloc_pages(gfp_mask, cur_order); - if (chunk->mem[chunk->npages].page) { - chunk->mem[chunk->npages].length = PAGE_SIZE << cur_order; - chunk->mem[chunk->npages].offset = 0; - - if (++chunk->npages == MLX4_ICM_CHUNK_LEN) { - chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - if (chunk->nsg <= 0) - goto fail; - - chunk = NULL; - } - - npages -= 1 << cur_order; - } else { - --cur_order; - if (cur_order < 0) - goto fail; - } - } - - if (chunk) { - chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - if (chunk->nsg <= 0) - goto fail; - } - - return icm; - -fail: - mlx4_free_icm(dev, icm); - return NULL; -} - -static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM, icm, virt); -} - -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count) -{ - return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt) -{ - struct mlx4_cmd_mailbox *mailbox; - __be64 *inbox; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - inbox[0] = cpu_to_be64(virt); - inbox[1] = cpu_to_be64(dma_addr); - - err = mlx4_cmd(dev, mailbox->dma, 1, 0, MLX4_CMD_MAP_ICM, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - - if (!err) - mlx4_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", - (unsigned long long) dma_addr, (unsigned long long) virt); - - return err; -} - -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM_AUX, icm, -1); -} - -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_ICM_AUX, MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) -{ - int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - int ret = 0; - - mutex_lock(&table->mutex); - - if (table->icm[i]) { - ++table->icm[i]->refcount; - goto out; - } - - table->icm[i] = mlx4_alloc_icm(dev, MLX4_TABLE_CHUNK_SIZE >> PAGE_SHIFT, - (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) | - __GFP_NOWARN); - if (!table->icm[i]) { - ret = -ENOMEM; - goto out; - } - - if (mlx4_MAP_ICM(dev, table->icm[i], table->virt + - (u64) i * MLX4_TABLE_CHUNK_SIZE)) { - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - ret = -ENOMEM; - goto out; - } - - ++table->icm[i]->refcount; - -out: - mutex_unlock(&table->mutex); - return ret; -} - -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) -{ - int i; - - i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - - mutex_lock(&table->mutex); - - if (--table->icm[i]->refcount == 0) { - mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - } - - mutex_unlock(&table->mutex); -} - -void *mlx4_table_find(struct mlx4_icm_table *table, int obj) -{ - int idx, offset, i; - struct mlx4_icm_chunk *chunk; - struct mlx4_icm *icm; - struct page *page = NULL; - - if (!table->lowmem) - return NULL; - - mutex_lock(&table->mutex); - - idx = obj & (table->num_obj - 1); - icm = table->icm[idx / (MLX4_TABLE_CHUNK_SIZE / table->obj_size)]; - offset = idx % (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - - if (!icm) - goto out; - - list_for_each_entry(chunk, &icm->chunk_list, list) { - for (i = 0; i < chunk->npages; ++i) { - if (chunk->mem[i].length > offset) { - page = chunk->mem[i].page; - goto out; - } - offset -= chunk->mem[i].length; - } - } - -out: - mutex_unlock(&table->mutex); - return page ? lowmem_page_address(page) + offset : NULL; -} - -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end) -{ - int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; - int i, err; - - for (i = start; i <= end; i += inc) { - err = mlx4_table_get(dev, table, i); - if (err) - goto fail; - } - - return 0; - -fail: - while (i > start) { - i -= inc; - mlx4_table_put(dev, table, i); - } - - return err; -} - -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end) -{ - int i; - - for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) - mlx4_table_put(dev, table, i); -} - -int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, - int use_lowmem) -{ - int obj_per_chunk; - int num_icm; - unsigned chunk_size; - int i; - - obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size; - num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk; - - table->icm = kcalloc(num_icm, sizeof *table->icm, GFP_KERNEL); - if (!table->icm) - return -ENOMEM; - table->virt = virt; - table->num_icm = num_icm; - table->num_obj = nobj; - table->obj_size = obj_size; - table->lowmem = use_lowmem; - mutex_init(&table->mutex); - - for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { - chunk_size = MLX4_TABLE_CHUNK_SIZE; - if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > nobj * obj_size) - chunk_size = PAGE_ALIGN(nobj * obj_size - i * MLX4_TABLE_CHUNK_SIZE); - - table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, - (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | - __GFP_NOWARN); - if (!table->icm[i]) - goto err; - if (mlx4_MAP_ICM(dev, table->icm[i], virt + i * MLX4_TABLE_CHUNK_SIZE)) { - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - goto err; - } - - /* - * Add a reference to this ICM chunk so that it never - * gets freed (since it contains reserved firmware objects). - */ - ++table->icm[i]->refcount; - } - - return 0; - -err: - for (i = 0; i < num_icm; ++i) - if (table->icm[i]) { - mlx4_UNMAP_ICM(dev, virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - } - - return -ENOMEM; -} - -void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table) -{ - int i; - - for (i = 0; i < table->num_icm; ++i) - if (table->icm[i]) { - mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - } - - kfree(table->icm); -} diff --git a/trunk/drivers/net/mlx4/icm.h b/trunk/drivers/net/mlx4/icm.h deleted file mode 100644 index bea223d879a5..000000000000 --- a/trunk/drivers/net/mlx4/icm.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, 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 MLX4_ICM_H -#define MLX4_ICM_H - -#include -#include -#include - -#define MLX4_ICM_CHUNK_LEN \ - ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ - (sizeof (struct scatterlist))) - -enum { - MLX4_ICM_PAGE_SHIFT = 12, - MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, -}; - -struct mlx4_icm_chunk { - struct list_head list; - int npages; - int nsg; - struct scatterlist mem[MLX4_ICM_CHUNK_LEN]; -}; - -struct mlx4_icm { - struct list_head chunk_list; - int refcount; -}; - -struct mlx4_icm_iter { - struct mlx4_icm *icm; - struct mlx4_icm_chunk *chunk; - int page_idx; -}; - -struct mlx4_dev; - -struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, gfp_t gfp_mask); -void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm); - -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, - int use_lowmem); -void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void *mlx4_table_find(struct mlx4_icm_table *table, int obj); -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); - -static inline void mlx4_icm_first(struct mlx4_icm *icm, - struct mlx4_icm_iter *iter) -{ - iter->icm = icm; - iter->chunk = list_empty(&icm->chunk_list) ? - NULL : list_entry(icm->chunk_list.next, - struct mlx4_icm_chunk, list); - iter->page_idx = 0; -} - -static inline int mlx4_icm_last(struct mlx4_icm_iter *iter) -{ - return !iter->chunk; -} - -static inline void mlx4_icm_next(struct mlx4_icm_iter *iter) -{ - if (++iter->page_idx >= iter->chunk->nsg) { - if (iter->chunk->list.next == &iter->icm->chunk_list) { - iter->chunk = NULL; - return; - } - - iter->chunk = list_entry(iter->chunk->list.next, - struct mlx4_icm_chunk, list); - iter->page_idx = 0; - } -} - -static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) -{ - return sg_dma_address(&iter->chunk->mem[iter->page_idx]); -} - -static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) -{ - return sg_dma_len(&iter->chunk->mem[iter->page_idx]); -} - -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count); -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt); -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); - -#endif /* MLX4_ICM_H */ diff --git a/trunk/drivers/net/mlx4/intf.c b/trunk/drivers/net/mlx4/intf.c deleted file mode 100644 index 65854f9e9c76..000000000000 --- a/trunk/drivers/net/mlx4/intf.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" - -struct mlx4_device_context { - struct list_head list; - struct mlx4_interface *intf; - void *context; -}; - -static LIST_HEAD(intf_list); -static LIST_HEAD(dev_list); -static DEFINE_MUTEX(intf_mutex); - -static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - dev_ctx = kmalloc(sizeof *dev_ctx, GFP_KERNEL); - if (!dev_ctx) - return; - - dev_ctx->intf = intf; - dev_ctx->context = intf->add(&priv->dev); - - if (dev_ctx->context) { - spin_lock_irq(&priv->ctx_lock); - list_add_tail(&dev_ctx->list, &priv->ctx_list); - spin_unlock_irq(&priv->ctx_lock); - } else - kfree(dev_ctx); -} - -static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf == intf) { - spin_lock_irq(&priv->ctx_lock); - list_del(&dev_ctx->list); - spin_unlock_irq(&priv->ctx_lock); - - intf->remove(&priv->dev, dev_ctx->context); - kfree(dev_ctx); - return; - } -} - -int mlx4_register_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - if (!intf->add || !intf->remove) - return -EINVAL; - - mutex_lock(&intf_mutex); - - list_add_tail(&intf->list, &intf_list); - list_for_each_entry(priv, &dev_list, dev_list) - mlx4_add_device(intf, priv); - - mutex_unlock(&intf_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_register_interface); - -void mlx4_unregister_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - mutex_lock(&intf_mutex); - - list_for_each_entry(priv, &dev_list, dev_list) - mlx4_remove_device(intf, priv); - - list_del(&intf->list); - - mutex_unlock(&intf_mutex); -} -EXPORT_SYMBOL_GPL(mlx4_unregister_interface); - -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type, - int subtype, int port) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_device_context *dev_ctx; - unsigned long flags; - - spin_lock_irqsave(&priv->ctx_lock, flags); - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf->event) - dev_ctx->intf->event(dev, dev_ctx->context, type, - subtype, port); - - spin_unlock_irqrestore(&priv->ctx_lock, flags); -} - -int mlx4_register_device(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; - - INIT_LIST_HEAD(&priv->ctx_list); - spin_lock_init(&priv->ctx_lock); - - mutex_lock(&intf_mutex); - - list_add_tail(&priv->dev_list, &dev_list); - list_for_each_entry(intf, &intf_list, list) - mlx4_add_device(intf, priv); - - mutex_unlock(&intf_mutex); - - return 0; -} - -void mlx4_unregister_device(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; - - mutex_lock(&intf_mutex); - - list_for_each_entry(intf, &intf_list, list) - mlx4_remove_device(intf, priv); - - list_del(&priv->dev_list); - - mutex_unlock(&intf_mutex); -} diff --git a/trunk/drivers/net/mlx4/main.c b/trunk/drivers/net/mlx4/main.c deleted file mode 100644 index 4debb024eaf9..000000000000 --- a/trunk/drivers/net/mlx4/main.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "fw.h" -#include "icm.h" - -MODULE_AUTHOR("Roland Dreier"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -#ifdef CONFIG_MLX4_DEBUG - -int mlx4_debug_level = 0; -module_param_named(debug_level, mlx4_debug_level, int, 0644); -MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); - -#endif /* CONFIG_MLX4_DEBUG */ - -#ifdef CONFIG_PCI_MSI - -static int msi_x; -module_param(msi_x, int, 0444); -MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); - -#else /* CONFIG_PCI_MSI */ - -#define msi_x (0) - -#endif /* CONFIG_PCI_MSI */ - -static const char mlx4_version[] __devinitdata = - DRV_NAME ": Mellanox ConnectX core driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; - -static struct mlx4_profile default_profile = { - .num_qp = 1 << 16, - .num_srq = 1 << 16, - .rdmarc_per_qp = 4, - .num_cq = 1 << 16, - .num_mcg = 1 << 13, - .num_mpt = 1 << 17, - .num_mtt = 1 << 20, -}; - -static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) -{ - int err; - - err = mlx4_QUERY_DEV_CAP(dev, dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - return err; - } - - if (dev_cap->min_page_sz > PAGE_SIZE) { - mlx4_err(dev, "HCA minimum page size of %d bigger than " - "kernel PAGE_SIZE of %ld, aborting.\n", - dev_cap->min_page_sz, PAGE_SIZE); - return -ENODEV; - } - if (dev_cap->num_ports > MLX4_MAX_PORTS) { - mlx4_err(dev, "HCA has %d ports, but we only support %d, " - "aborting.\n", - dev_cap->num_ports, MLX4_MAX_PORTS); - return -ENODEV; - } - - if (dev_cap->uar_size > pci_resource_len(dev->pdev, 2)) { - mlx4_err(dev, "HCA reported UAR size of 0x%x bigger than " - "PCI resource 2 size of 0x%llx, aborting.\n", - dev_cap->uar_size, - (unsigned long long) pci_resource_len(dev->pdev, 2)); - return -ENODEV; - } - - dev->caps.num_ports = dev_cap->num_ports; - dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; - dev->caps.vl_cap = dev_cap->max_vl; - dev->caps.mtu_cap = dev_cap->max_mtu; - dev->caps.gid_table_len = dev_cap->max_gids; - dev->caps.pkey_table_len = dev_cap->max_pkeys; - dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; - dev->caps.bf_reg_size = dev_cap->bf_reg_size; - dev->caps.bf_regs_per_page = dev_cap->bf_regs_per_page; - dev->caps.max_sq_sg = dev_cap->max_sq_sg; - dev->caps.max_rq_sg = dev_cap->max_rq_sg; - dev->caps.max_wqes = dev_cap->max_qp_sz; - dev->caps.max_qp_init_rdma = dev_cap->max_requester_per_qp; - dev->caps.reserved_qps = dev_cap->reserved_qps; - dev->caps.max_srq_wqes = dev_cap->max_srq_sz; - dev->caps.max_srq_sge = dev_cap->max_rq_sg - 1; - dev->caps.reserved_srqs = dev_cap->reserved_srqs; - dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; - dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; - dev->caps.num_qp_per_mgm = MLX4_QP_PER_MGM; - /* - * Subtract 1 from the limit because we need to allocate a - * spare CQE so the HCA HW can tell the difference between an - * empty CQ and a full CQ. - */ - dev->caps.max_cqes = dev_cap->max_cq_sz - 1; - dev->caps.reserved_cqs = dev_cap->reserved_cqs; - dev->caps.reserved_eqs = dev_cap->reserved_eqs; - dev->caps.reserved_mtts = dev_cap->reserved_mtts; - dev->caps.reserved_mrws = dev_cap->reserved_mrws; - dev->caps.reserved_uars = dev_cap->reserved_uars; - dev->caps.reserved_pds = dev_cap->reserved_pds; - dev->caps.port_width_cap = dev_cap->max_port_width; - dev->caps.mtt_entry_sz = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; - dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); - dev->caps.flags = dev_cap->flags; - dev->caps.stat_rate_support = dev_cap->stat_rate_support; - - return 0; -} - -static int __devinit mlx4_load_fw(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages, - GFP_HIGHUSER | __GFP_NOWARN); - if (!priv->fw.fw_icm) { - mlx4_err(dev, "Couldn't allocate FW area, aborting.\n"); - return -ENOMEM; - } - - err = mlx4_MAP_FA(dev, priv->fw.fw_icm); - if (err) { - mlx4_err(dev, "MAP_FA command failed, aborting.\n"); - goto err_free; - } - - err = mlx4_RUN_FW(dev); - if (err) { - mlx4_err(dev, "RUN_FW command failed, aborting.\n"); - goto err_unmap_fa; - } - - return 0; - -err_unmap_fa: - mlx4_UNMAP_FA(dev); - -err_free: - mlx4_free_icm(dev, priv->fw.fw_icm); - return err; -} - -static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, - int cmpt_entry_sz) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - err = mlx4_init_icm_table(dev, &priv->qp_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_QP * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) - goto err; - - err = mlx4_init_icm_table(dev, &priv->srq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_SRQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_srqs, - dev->caps.reserved_srqs, 0); - if (err) - goto err_qp; - - err = mlx4_init_icm_table(dev, &priv->cq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_CQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_cqs, - dev->caps.reserved_cqs, 0); - if (err) - goto err_srq; - - err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_EQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, - roundup_pow_of_two(MLX4_NUM_EQ + - dev->caps.reserved_eqs), - MLX4_NUM_EQ + dev->caps.reserved_eqs, 0); - if (err) - goto err_cq; - - return 0; - -err_cq: - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - -err_srq: - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - -err_qp: - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - -err: - return err; -} - -static int __devinit mlx4_init_icm(struct mlx4_dev *dev, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca, - u64 icm_size) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u64 aux_pages; - int err; - - err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages); - if (err) { - mlx4_err(dev, "SET_ICM_SIZE command failed, aborting.\n"); - return err; - } - - mlx4_dbg(dev, "%lld KB of HCA context requires %lld KB aux memory.\n", - (unsigned long long) icm_size >> 10, - (unsigned long long) aux_pages << 2); - - priv->fw.aux_icm = mlx4_alloc_icm(dev, aux_pages, - GFP_HIGHUSER | __GFP_NOWARN); - if (!priv->fw.aux_icm) { - mlx4_err(dev, "Couldn't allocate aux memory, aborting.\n"); - return -ENOMEM; - } - - err = mlx4_MAP_ICM_AUX(dev, priv->fw.aux_icm); - if (err) { - mlx4_err(dev, "MAP_ICM_AUX command failed, aborting.\n"); - goto err_free_aux; - } - - err = mlx4_init_cmpt_table(dev, init_hca->cmpt_base, dev_cap->cmpt_entry_sz); - if (err) { - mlx4_err(dev, "Failed to map cMPT context memory, aborting.\n"); - goto err_unmap_aux; - } - - err = mlx4_map_eq_icm(dev, init_hca->eqc_base); - if (err) { - mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); - goto err_unmap_cmpt; - } - - err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table, - init_hca->mtt_base, - dev->caps.mtt_entry_sz, - dev->caps.num_mtt_segs, - dev->caps.reserved_mtts, 1); - if (err) { - mlx4_err(dev, "Failed to map MTT context memory, aborting.\n"); - goto err_unmap_eq; - } - - err = mlx4_init_icm_table(dev, &priv->mr_table.dmpt_table, - init_hca->dmpt_base, - dev_cap->dmpt_entry_sz, - dev->caps.num_mpts, - dev->caps.reserved_mrws, 1); - if (err) { - mlx4_err(dev, "Failed to map dMPT context memory, aborting.\n"); - goto err_unmap_mtt; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.qp_table, - init_hca->qpc_base, - dev_cap->qpc_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map QP context memory, aborting.\n"); - goto err_unmap_dmpt; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.auxc_table, - init_hca->auxc_base, - dev_cap->aux_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n"); - goto err_unmap_qp; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.altc_table, - init_hca->altc_base, - dev_cap->altc_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n"); - goto err_unmap_auxc; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.rdmarc_table, - init_hca->rdmarc_base, - dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n"); - goto err_unmap_altc; - } - - err = mlx4_init_icm_table(dev, &priv->cq_table.table, - init_hca->cqc_base, - dev_cap->cqc_entry_sz, - dev->caps.num_cqs, - dev->caps.reserved_cqs, 0); - if (err) { - mlx4_err(dev, "Failed to map CQ context memory, aborting.\n"); - goto err_unmap_rdmarc; - } - - err = mlx4_init_icm_table(dev, &priv->srq_table.table, - init_hca->srqc_base, - dev_cap->srq_entry_sz, - dev->caps.num_srqs, - dev->caps.reserved_srqs, 0); - if (err) { - mlx4_err(dev, "Failed to map SRQ context memory, aborting.\n"); - goto err_unmap_cq; - } - - /* - * It's not strictly required, but for simplicity just map the - * whole multicast group table now. The table isn't very big - * and it's a lot easier than trying to track ref counts. - */ - err = mlx4_init_icm_table(dev, &priv->mcg_table.table, - init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, - dev->caps.num_mgms + dev->caps.num_amgms, - dev->caps.num_mgms + dev->caps.num_amgms, - 0); - if (err) { - mlx4_err(dev, "Failed to map MCG context memory, aborting.\n"); - goto err_unmap_srq; - } - - return 0; - -err_unmap_srq: - mlx4_cleanup_icm_table(dev, &priv->srq_table.table); - -err_unmap_cq: - mlx4_cleanup_icm_table(dev, &priv->cq_table.table); - -err_unmap_rdmarc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table); - -err_unmap_altc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table); - -err_unmap_auxc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table); - -err_unmap_qp: - mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); - -err_unmap_dmpt: - mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); - -err_unmap_mtt: - mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); - -err_unmap_eq: - mlx4_unmap_eq_icm(dev); - -err_unmap_cmpt: - mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - -err_unmap_aux: - mlx4_UNMAP_ICM_AUX(dev); - -err_free_aux: - mlx4_free_icm(dev, priv->fw.aux_icm); - - return err; -} - -static void mlx4_free_icms(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mlx4_cleanup_icm_table(dev, &priv->mcg_table.table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); - mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); - mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); - mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - mlx4_unmap_eq_icm(dev); - - mlx4_UNMAP_ICM_AUX(dev); - mlx4_free_icm(dev, priv->fw.aux_icm); -} - -static void mlx4_close_hca(struct mlx4_dev *dev) -{ - mlx4_CLOSE_HCA(dev, 0); - mlx4_free_icms(dev); - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm); -} - -static int __devinit mlx4_init_hca(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_adapter adapter; - struct mlx4_dev_cap dev_cap; - struct mlx4_profile profile; - struct mlx4_init_hca_param init_hca; - u64 icm_size; - int err; - - err = mlx4_QUERY_FW(dev); - if (err) { - mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - return err; - } - - err = mlx4_load_fw(dev); - if (err) { - mlx4_err(dev, "Failed to start FW, aborting.\n"); - return err; - } - - err = mlx4_dev_cap(dev, &dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - goto err_stop_fw; - } - - profile = default_profile; - - icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca); - if ((long long) icm_size < 0) { - err = icm_size; - goto err_stop_fw; - } - - init_hca.log_uar_sz = ilog2(dev->caps.num_uars); - - err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); - if (err) - goto err_stop_fw; - - err = mlx4_INIT_HCA(dev, &init_hca); - if (err) { - mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); - goto err_free_icm; - } - - err = mlx4_QUERY_ADAPTER(dev, &adapter); - if (err) { - mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); - goto err_close; - } - - priv->eq_table.inta_pin = adapter.inta_pin; - priv->rev_id = adapter.revision_id; - memcpy(priv->board_id, adapter.board_id, sizeof priv->board_id); - - return 0; - -err_close: - mlx4_close_hca(dev); - -err_free_icm: - mlx4_free_icms(dev); - -err_stop_fw: - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, priv->fw.fw_icm); - - return err; -} - -static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - MLX4_INIT_DOORBELL_LOCK(&priv->doorbell_lock); - - err = mlx4_init_uar_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "user access region table, aborting.\n"); - return err; - } - - err = mlx4_uar_alloc(dev, &priv->driver_uar); - if (err) { - mlx4_err(dev, "Failed to allocate driver access region, " - "aborting.\n"); - goto err_uar_table_free; - } - - priv->kar = ioremap(priv->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!priv->kar) { - mlx4_err(dev, "Couldn't map kernel access region, " - "aborting.\n"); - err = -ENOMEM; - goto err_uar_free; - } - - err = mlx4_init_pd_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "protection domain table, aborting.\n"); - goto err_kar_unmap; - } - - err = mlx4_init_mr_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "memory region table, aborting.\n"); - goto err_pd_table_free; - } - - mlx4_map_catas_buf(dev); - - err = mlx4_init_eq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "event queue table, aborting.\n"); - goto err_catas_buf; - } - - err = mlx4_cmd_use_events(dev); - if (err) { - mlx4_err(dev, "Failed to switch to event-driven " - "firmware commands, aborting.\n"); - goto err_eq_table_free; - } - - err = mlx4_NOP(dev); - if (err) { - mlx4_err(dev, "NOP command failed to generate interrupt " - "(IRQ %d), aborting.\n", - priv->eq_table.eq[MLX4_EQ_ASYNC].irq); - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_err(dev, "Try again with MSI-X disabled.\n"); - else - mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); - - goto err_cmd_poll; - } - - mlx4_dbg(dev, "NOP command IRQ test passed\n"); - - err = mlx4_init_cq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "completion queue table, aborting.\n"); - goto err_cmd_poll; - } - - err = mlx4_init_srq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "shared receive queue table, aborting.\n"); - goto err_cq_table_free; - } - - err = mlx4_init_qp_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "queue pair table, aborting.\n"); - goto err_srq_table_free; - } - - err = mlx4_init_mcg_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "multicast group table, aborting.\n"); - goto err_qp_table_free; - } - - return 0; - -err_qp_table_free: - mlx4_cleanup_qp_table(dev); - -err_srq_table_free: - mlx4_cleanup_srq_table(dev); - -err_cq_table_free: - mlx4_cleanup_cq_table(dev); - -err_cmd_poll: - mlx4_cmd_use_polling(dev); - -err_eq_table_free: - mlx4_cleanup_eq_table(dev); - -err_catas_buf: - mlx4_unmap_catas_buf(dev); - mlx4_cleanup_mr_table(dev); - -err_pd_table_free: - mlx4_cleanup_pd_table(dev); - -err_kar_unmap: - iounmap(priv->kar); - -err_uar_free: - mlx4_uar_free(dev, &priv->driver_uar); - -err_uar_table_free: - mlx4_cleanup_uar_table(dev); - return err; -} - -static void __devinit mlx4_enable_msi_x(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct msix_entry entries[MLX4_NUM_EQ]; - int err; - int i; - - if (msi_x) { - for (i = 0; i < MLX4_NUM_EQ; ++i) - entries[i].entry = i; - - err = pci_enable_msix(dev->pdev, entries, ARRAY_SIZE(entries)); - if (err) { - if (err > 0) - mlx4_info(dev, "Only %d MSI-X vectors available, " - "not using MSI-X\n", err); - goto no_msi; - } - - for (i = 0; i < MLX4_NUM_EQ; ++i) - priv->eq_table.eq[i].irq = entries[i].vector; - - dev->flags |= MLX4_FLAG_MSI_X; - return; - } - -no_msi: - for (i = 0; i < MLX4_NUM_EQ; ++i) - priv->eq_table.eq[i].irq = dev->pdev->irq; -} - -static int __devinit mlx4_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - static int mlx4_version_printed; - struct mlx4_priv *priv; - struct mlx4_dev *dev; - int err; - - if (!mlx4_version_printed) { - printk(KERN_INFO "%s", mlx4_version); - ++mlx4_version_printed; - } - - printk(KERN_INFO PFX "Initializing %s\n", - pci_name(pdev)); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Cannot enable PCI device, " - "aborting.\n"); - return err; - } - - /* - * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not - * be present) - */ - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || - pci_resource_len(pdev, 0) != 1 << 20) { - dev_err(&pdev->dev, "Missing DCS, aborting.\n"); - err = -ENODEV; - goto err_disable_pdev; - } - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "Missing UAR, aborting.\n"); - err = -ENODEV; - goto err_disable_pdev; - } - - err = pci_request_region(pdev, 0, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "Cannot request control region, aborting.\n"); - goto err_disable_pdev; - } - - err = pci_request_region(pdev, 2, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "Cannot request UAR region, aborting.\n"); - goto err_release_bar0; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (err) { - dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n"); - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); - goto err_release_bar2; - } - } - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err) { - dev_warn(&pdev->dev, "Warning: couldn't set 64-bit " - "consistent PCI DMA mask.\n"); - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " - "aborting.\n"); - goto err_release_bar2; - } - } - - priv = kzalloc(sizeof *priv, GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "Device struct alloc failed, " - "aborting.\n"); - err = -ENOMEM; - goto err_release_bar2; - } - - dev = &priv->dev; - dev->pdev = pdev; - - /* - * Now reset the HCA before we touch the PCI capabilities or - * attempt a firmware command, since a boot ROM may have left - * the HCA in an undefined state. - */ - err = mlx4_reset(dev); - if (err) { - mlx4_err(dev, "Failed to reset HCA, aborting.\n"); - goto err_free_dev; - } - - mlx4_enable_msi_x(dev); - - if (mlx4_cmd_init(dev)) { - mlx4_err(dev, "Failed to init command interface, aborting.\n"); - goto err_free_dev; - } - - err = mlx4_init_hca(dev); - if (err) - goto err_cmd; - - err = mlx4_setup_hca(dev); - if (err) - goto err_close; - - err = mlx4_register_device(dev); - if (err) - goto err_cleanup; - - pci_set_drvdata(pdev, dev); - - return 0; - -err_cleanup: - mlx4_cleanup_mcg_table(dev); - mlx4_cleanup_qp_table(dev); - mlx4_cleanup_srq_table(dev); - mlx4_cleanup_cq_table(dev); - mlx4_cmd_use_polling(dev); - mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - - mlx4_cleanup_mr_table(dev); - mlx4_cleanup_pd_table(dev); - mlx4_cleanup_uar_table(dev); - -err_close: - mlx4_close_hca(dev); - -err_cmd: - mlx4_cmd_cleanup(dev); - -err_free_dev: - if (dev->flags & MLX4_FLAG_MSI_X) - pci_disable_msix(pdev); - - kfree(priv); - -err_release_bar2: - pci_release_region(pdev, 2); - -err_release_bar0: - pci_release_region(pdev, 0); - -err_disable_pdev: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit mlx4_remove_one(struct pci_dev *pdev) -{ - struct mlx4_dev *dev = pci_get_drvdata(pdev); - struct mlx4_priv *priv = mlx4_priv(dev); - int p; - - if (dev) { - mlx4_unregister_device(dev); - - for (p = 1; p <= dev->caps.num_ports; ++p) - mlx4_CLOSE_PORT(dev, p); - - mlx4_cleanup_mcg_table(dev); - mlx4_cleanup_qp_table(dev); - mlx4_cleanup_srq_table(dev); - mlx4_cleanup_cq_table(dev); - mlx4_cmd_use_polling(dev); - mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - - mlx4_cleanup_mr_table(dev); - mlx4_cleanup_pd_table(dev); - - iounmap(priv->kar); - mlx4_uar_free(dev, &priv->driver_uar); - mlx4_cleanup_uar_table(dev); - mlx4_close_hca(dev); - mlx4_cmd_cleanup(dev); - - if (dev->flags & MLX4_FLAG_MSI_X) - pci_disable_msix(pdev); - - kfree(priv); - pci_release_region(pdev, 2); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static struct pci_device_id mlx4_pci_table[] = { - { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ - { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ - { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, mlx4_pci_table); - -static struct pci_driver mlx4_driver = { - .name = DRV_NAME, - .id_table = mlx4_pci_table, - .probe = mlx4_init_one, - .remove = __devexit_p(mlx4_remove_one) -}; - -static int __init mlx4_init(void) -{ - int ret; - - ret = pci_register_driver(&mlx4_driver); - return ret < 0 ? ret : 0; -} - -static void __exit mlx4_cleanup(void) -{ - pci_unregister_driver(&mlx4_driver); -} - -module_init(mlx4_init); -module_exit(mlx4_cleanup); diff --git a/trunk/drivers/net/mlx4/mcg.c b/trunk/drivers/net/mlx4/mcg.c deleted file mode 100644 index 672024a0ee71..000000000000 --- a/trunk/drivers/net/mlx4/mcg.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" - -struct mlx4_mgm { - __be32 next_gid_index; - __be32 members_count; - u32 reserved[2]; - u8 gid[16]; - __be32 qp[MLX4_QP_PER_MGM]; -}; - -static const u8 zero_gid[16]; /* automatically initialized to 0 */ - -static int mlx4_READ_MCG(struct mlx4_dev *dev, int index, - struct mlx4_cmd_mailbox *mailbox) -{ - return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, - struct mlx4_cmd_mailbox *mailbox) -{ - return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - u16 *hash) -{ - u64 imm; - int err; - - err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH, - MLX4_CMD_TIME_CLASS_A); - - if (!err) - *hash = imm; - - return err; -} - -/* - * Caller must hold MCG table semaphore. gid and mgm parameters must - * be properly aligned for command interface. - * - * Returns 0 unless a firmware command error occurs. - * - * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 - * and *mgm holds MGM entry. - * - * if GID is found in AMGM, *index = index in AMGM, *prev = index of - * previous entry in hash chain and *mgm holds AMGM entry. - * - * If no AMGM exists for given gid, *index = -1, *prev = index of last - * entry in hash chain and *mgm holds end of hash chain. - */ -static int find_mgm(struct mlx4_dev *dev, - u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox, - u16 *hash, int *prev, int *index) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm = mgm_mailbox->buf; - u8 *mgid; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return -ENOMEM; - mgid = mailbox->buf; - - memcpy(mgid, gid, 16); - - err = mlx4_MGID_HASH(dev, mailbox, hash); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - return err; - - if (0) - mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:" - "%04x:%04x:%04x:%04x is %04x\n", - be16_to_cpu(((__be16 *) gid)[0]), - be16_to_cpu(((__be16 *) gid)[1]), - be16_to_cpu(((__be16 *) gid)[2]), - be16_to_cpu(((__be16 *) gid)[3]), - be16_to_cpu(((__be16 *) gid)[4]), - be16_to_cpu(((__be16 *) gid)[5]), - be16_to_cpu(((__be16 *) gid)[6]), - be16_to_cpu(((__be16 *) gid)[7]), - *hash); - - *index = *hash; - *prev = -1; - - do { - err = mlx4_READ_MCG(dev, *index, mgm_mailbox); - if (err) - return err; - - if (!memcmp(mgm->gid, zero_gid, 16)) { - if (*index != *hash) { - mlx4_err(dev, "Found zero MGID in AMGM.\n"); - err = -EINVAL; - } - return err; - } - - if (!memcmp(mgm->gid, gid, 16)) - return err; - - *prev = *index; - *index = be32_to_cpu(mgm->next_gid_index) >> 6; - } while (*index); - - *index = -1; - return err; -} - -int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm; - u32 members_count; - u16 hash; - int index, prev; - int link = 0; - int i; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - mgm = mailbox->buf; - - mutex_lock(&priv->mcg_table.mutex); - - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); - if (err) - goto out; - - if (index != -1) { - if (!memcmp(mgm->gid, zero_gid, 16)) - memcpy(mgm->gid, gid, 16); - } else { - link = 1; - - index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); - if (index == -1) { - mlx4_err(dev, "No AMGM entries left\n"); - err = -ENOMEM; - goto out; - } - index += dev->caps.num_mgms; - - err = mlx4_READ_MCG(dev, index, mailbox); - if (err) - goto out; - - memset(mgm, 0, sizeof *mgm); - memcpy(mgm->gid, gid, 16); - } - - members_count = be32_to_cpu(mgm->members_count); - if (members_count == MLX4_QP_PER_MGM) { - mlx4_err(dev, "MGM at index %x is full.\n", index); - err = -ENOMEM; - goto out; - } - - for (i = 0; i < members_count; ++i) - if (mgm->qp[i] == cpu_to_be32(qp->qpn)) { - mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); - err = 0; - goto out; - } - - mgm->qp[members_count++] = cpu_to_be32(qp->qpn); - mgm->members_count = cpu_to_be32(members_count); - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (!link) - goto out; - - err = mlx4_READ_MCG(dev, prev, mailbox); - if (err) - goto out; - - mgm->next_gid_index = cpu_to_be32(index << 6); - - err = mlx4_WRITE_MCG(dev, prev, mailbox); - if (err) - goto out; - -out: - if (err && link && index != -1) { - if (index < dev->caps.num_mgms) - mlx4_warn(dev, "Got AMGM index %d < %d", - index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); - } - mutex_unlock(&priv->mcg_table.mutex); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_multicast_attach); - -int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm; - u32 members_count; - u16 hash; - int prev, index; - int i, loc; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - mgm = mailbox->buf; - - mutex_lock(&priv->mcg_table.mutex); - - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); - if (err) - goto out; - - if (index == -1) { - mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " - "not found\n", - be16_to_cpu(((__be16 *) gid)[0]), - be16_to_cpu(((__be16 *) gid)[1]), - be16_to_cpu(((__be16 *) gid)[2]), - be16_to_cpu(((__be16 *) gid)[3]), - be16_to_cpu(((__be16 *) gid)[4]), - be16_to_cpu(((__be16 *) gid)[5]), - be16_to_cpu(((__be16 *) gid)[6]), - be16_to_cpu(((__be16 *) gid)[7])); - err = -EINVAL; - goto out; - } - - members_count = be32_to_cpu(mgm->members_count); - for (loc = -1, i = 0; i < members_count; ++i) - if (mgm->qp[i] == cpu_to_be32(qp->qpn)) - loc = i; - - if (loc == -1) { - mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); - err = -EINVAL; - goto out; - } - - - mgm->members_count = cpu_to_be32(--members_count); - mgm->qp[loc] = mgm->qp[i - 1]; - mgm->qp[i - 1] = 0; - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (i != 1) - goto out; - - if (prev == -1) { - /* Remove entry from MGM */ - int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; - if (amgm_index) { - err = mlx4_READ_MCG(dev, amgm_index, mailbox); - if (err) - goto out; - } else - memset(mgm->gid, 0, 16); - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (amgm_index) { - if (amgm_index < dev->caps.num_mgms) - mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", - index, amgm_index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - amgm_index - dev->caps.num_mgms); - } - } else { - /* Remove entry from AMGM */ - int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; - err = mlx4_READ_MCG(dev, prev, mailbox); - if (err) - goto out; - - mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); - - err = mlx4_WRITE_MCG(dev, prev, mailbox); - if (err) - goto out; - - if (index < dev->caps.num_mgms) - mlx4_warn(dev, "entry %d had next AMGM index %d < %d", - prev, index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); - } - -out: - mutex_unlock(&priv->mcg_table.mutex); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_multicast_detach); - -int __devinit mlx4_init_mcg_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - err = mlx4_bitmap_init(&priv->mcg_table.bitmap, - dev->caps.num_amgms, dev->caps.num_amgms - 1, 0); - if (err) - return err; - - mutex_init(&priv->mcg_table.mutex); - - return 0; -} - -void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/mlx4.h b/trunk/drivers/net/mlx4/mlx4.h deleted file mode 100644 index 9befbae3d196..000000000000 --- a/trunk/drivers/net/mlx4/mlx4.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, 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 MLX4_H -#define MLX4_H - -#include - -#include -#include - -#define DRV_NAME "mlx4_core" -#define PFX DRV_NAME ": " -#define DRV_VERSION "0.01" -#define DRV_RELDATE "May 1, 2007" - -enum { - MLX4_HCR_BASE = 0x80680, - MLX4_HCR_SIZE = 0x0001c, - MLX4_CLR_INT_SIZE = 0x00008 -}; - -enum { - MLX4_BOARD_ID_LEN = 64 -}; - -enum { - MLX4_MGM_ENTRY_SIZE = 0x40, - MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), - MLX4_MTT_ENTRY_PER_SEG = 8 -}; - -enum { - MLX4_EQ_ASYNC, - MLX4_EQ_COMP, - MLX4_EQ_CATAS, - MLX4_NUM_EQ -}; - -enum { - MLX4_NUM_PDS = 1 << 15 -}; - -enum { - MLX4_CMPT_TYPE_QP = 0, - MLX4_CMPT_TYPE_SRQ = 1, - MLX4_CMPT_TYPE_CQ = 2, - MLX4_CMPT_TYPE_EQ = 3, - MLX4_CMPT_NUM_TYPE -}; - -enum { - MLX4_CMPT_SHIFT = 24, - MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT -}; - -#ifdef CONFIG_MLX4_DEBUG -extern int mlx4_debug_level; - -#define mlx4_dbg(mdev, format, arg...) \ - do { \ - if (mlx4_debug_level) \ - dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ - } while (0) - -#else /* CONFIG_MLX4_DEBUG */ - -#define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0) - -#endif /* CONFIG_MLX4_DEBUG */ - -#define mlx4_err(mdev, format, arg...) \ - dev_err(&mdev->pdev->dev, format, ## arg) -#define mlx4_info(mdev, format, arg...) \ - dev_info(&mdev->pdev->dev, format, ## arg) -#define mlx4_warn(mdev, format, arg...) \ - dev_warn(&mdev->pdev->dev, format, ## arg) - -struct mlx4_bitmap { - u32 last; - u32 top; - u32 max; - u32 mask; - spinlock_t lock; - unsigned long *table; -}; - -struct mlx4_buddy { - unsigned long **bits; - int max_order; - spinlock_t lock; -}; - -struct mlx4_icm; - -struct mlx4_icm_table { - u64 virt; - int num_icm; - int num_obj; - int obj_size; - int lowmem; - struct mutex mutex; - struct mlx4_icm **icm; -}; - -struct mlx4_eq { - struct mlx4_dev *dev; - void __iomem *doorbell; - int eqn; - u32 cons_index; - u16 irq; - u16 have_irq; - int nent; - struct mlx4_buf_list *page_list; - struct mlx4_mtt mtt; -}; - -struct mlx4_profile { - int num_qp; - int rdmarc_per_qp; - int num_srq; - int num_cq; - int num_mcg; - int num_mpt; - int num_mtt; -}; - -struct mlx4_fw { - u64 clr_int_base; - u64 catas_offset; - struct mlx4_icm *fw_icm; - struct mlx4_icm *aux_icm; - u32 catas_size; - u16 fw_pages; - u8 clr_int_bar; - u8 catas_bar; -}; - -struct mlx4_cmd { - struct pci_pool *pool; - void __iomem *hcr; - struct mutex hcr_mutex; - struct semaphore poll_sem; - struct semaphore event_sem; - int max_cmds; - spinlock_t context_lock; - int free_head; - struct mlx4_cmd_context *context; - u16 token_mask; - u8 use_events; - u8 toggle; -}; - -struct mlx4_uar_table { - struct mlx4_bitmap bitmap; -}; - -struct mlx4_mr_table { - struct mlx4_bitmap mpt_bitmap; - struct mlx4_buddy mtt_buddy; - u64 mtt_base; - u64 mpt_base; - struct mlx4_icm_table mtt_table; - struct mlx4_icm_table dmpt_table; -}; - -struct mlx4_cq_table { - struct mlx4_bitmap bitmap; - spinlock_t lock; - struct radix_tree_root tree; - struct mlx4_icm_table table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_eq_table { - struct mlx4_bitmap bitmap; - void __iomem *clr_int; - void __iomem *uar_map[(MLX4_NUM_EQ + 6) / 4]; - u32 clr_mask; - struct mlx4_eq eq[MLX4_NUM_EQ]; - u64 icm_virt; - struct page *icm_page; - dma_addr_t icm_dma; - struct mlx4_icm_table cmpt_table; - int have_irq; - u8 inta_pin; -}; - -struct mlx4_srq_table { - struct mlx4_bitmap bitmap; - spinlock_t lock; - struct radix_tree_root tree; - struct mlx4_icm_table table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_qp_table { - struct mlx4_bitmap bitmap; - u32 rdmarc_base; - int rdmarc_shift; - spinlock_t lock; - struct mlx4_icm_table qp_table; - struct mlx4_icm_table auxc_table; - struct mlx4_icm_table altc_table; - struct mlx4_icm_table rdmarc_table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_mcg_table { - struct mutex mutex; - struct mlx4_bitmap bitmap; - struct mlx4_icm_table table; -}; - -struct mlx4_catas_err { - u32 __iomem *map; - int size; -}; - -struct mlx4_priv { - struct mlx4_dev dev; - - struct list_head dev_list; - struct list_head ctx_list; - spinlock_t ctx_lock; - - struct mlx4_fw fw; - struct mlx4_cmd cmd; - - struct mlx4_bitmap pd_bitmap; - struct mlx4_uar_table uar_table; - struct mlx4_mr_table mr_table; - struct mlx4_cq_table cq_table; - struct mlx4_eq_table eq_table; - struct mlx4_srq_table srq_table; - struct mlx4_qp_table qp_table; - struct mlx4_mcg_table mcg_table; - - struct mlx4_catas_err catas_err; - - void __iomem *clr_base; - - struct mlx4_uar driver_uar; - void __iomem *kar; - MLX4_DECLARE_DOORBELL_LOCK(doorbell_lock) - - u32 rev_id; - char board_id[MLX4_BOARD_ID_LEN]; -}; - -static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) -{ - return container_of(dev, struct mlx4_priv, dev); -} - -u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved); -void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap); - -int mlx4_reset(struct mlx4_dev *dev); - -int mlx4_init_pd_table(struct mlx4_dev *dev); -int mlx4_init_uar_table(struct mlx4_dev *dev); -int mlx4_init_mr_table(struct mlx4_dev *dev); -int mlx4_init_eq_table(struct mlx4_dev *dev); -int mlx4_init_cq_table(struct mlx4_dev *dev); -int mlx4_init_qp_table(struct mlx4_dev *dev); -int mlx4_init_srq_table(struct mlx4_dev *dev); -int mlx4_init_mcg_table(struct mlx4_dev *dev); - -void mlx4_cleanup_pd_table(struct mlx4_dev *dev); -void mlx4_cleanup_uar_table(struct mlx4_dev *dev); -void mlx4_cleanup_mr_table(struct mlx4_dev *dev); -void mlx4_cleanup_eq_table(struct mlx4_dev *dev); -void mlx4_cleanup_cq_table(struct mlx4_dev *dev); -void mlx4_cleanup_qp_table(struct mlx4_dev *dev); -void mlx4_cleanup_srq_table(struct mlx4_dev *dev); -void mlx4_cleanup_mcg_table(struct mlx4_dev *dev); - -void mlx4_map_catas_buf(struct mlx4_dev *dev); -void mlx4_unmap_catas_buf(struct mlx4_dev *dev); - -int mlx4_register_device(struct mlx4_dev *dev); -void mlx4_unregister_device(struct mlx4_dev *dev); -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type, - int subtype, int port); - -struct mlx4_dev_cap; -struct mlx4_init_hca_param; - -u64 mlx4_make_profile(struct mlx4_dev *dev, - struct mlx4_profile *request, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca); - -int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt); -void mlx4_unmap_eq_icm(struct mlx4_dev *dev); - -int mlx4_cmd_init(struct mlx4_dev *dev); -void mlx4_cmd_cleanup(struct mlx4_dev *dev); -void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); -int mlx4_cmd_use_events(struct mlx4_dev *dev); -void mlx4_cmd_use_polling(struct mlx4_dev *dev); - -void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); -void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); - -void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type); - -void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); - -void mlx4_handle_catas_err(struct mlx4_dev *dev); - -#endif /* MLX4_H */ diff --git a/trunk/drivers/net/mlx4/mr.c b/trunk/drivers/net/mlx4/mr.c deleted file mode 100644 index b33864dab179..000000000000 --- a/trunk/drivers/net/mlx4/mr.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "icm.h" - -/* - * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. - */ -struct mlx4_mpt_entry { - __be32 flags; - __be32 qpn; - __be32 key; - __be32 pd; - __be64 start; - __be64 length; - __be32 lkey; - __be32 win_cnt; - u8 reserved1[3]; - u8 mtt_rep; - __be64 mtt_seg; - __be32 mtt_sz; - __be32 entity_size; - __be32 first_byte_offset; -} __attribute__((packed)); - -#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) -#define MLX4_MPT_FLAG_MIO (1 << 17) -#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15) -#define MLX4_MPT_FLAG_PHYSICAL (1 << 9) -#define MLX4_MPT_FLAG_REGION (1 << 8) - -#define MLX4_MTT_FLAG_PRESENT 1 - -static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) -{ - int o; - int m; - u32 seg; - - spin_lock(&buddy->lock); - - for (o = order; o <= buddy->max_order; ++o) { - m = 1 << (buddy->max_order - o); - seg = find_first_bit(buddy->bits[o], m); - if (seg < m) - goto found; - } - - spin_unlock(&buddy->lock); - return -1; - - found: - clear_bit(seg, buddy->bits[o]); - - while (o > order) { - --o; - seg <<= 1; - set_bit(seg ^ 1, buddy->bits[o]); - } - - spin_unlock(&buddy->lock); - - seg <<= order; - - return seg; -} - -static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order) -{ - seg >>= order; - - spin_lock(&buddy->lock); - - while (test_bit(seg ^ 1, buddy->bits[order])) { - clear_bit(seg ^ 1, buddy->bits[order]); - seg >>= 1; - ++order; - } - - set_bit(seg, buddy->bits[order]); - - spin_unlock(&buddy->lock); -} - -static int __devinit mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) -{ - int i, s; - - buddy->max_order = max_order; - spin_lock_init(&buddy->lock); - - buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), - GFP_KERNEL); - if (!buddy->bits) - goto err_out; - - for (i = 0; i <= buddy->max_order; ++i) { - s = BITS_TO_LONGS(1 << (buddy->max_order - i)); - buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); - if (!buddy->bits[i]) - goto err_out_free; - bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); - } - - set_bit(0, buddy->bits[buddy->max_order]); - - return 0; - -err_out_free: - for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); - - kfree(buddy->bits); - -err_out: - return -ENOMEM; -} - -static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) -{ - int i; - - for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); - - kfree(buddy->bits); -} - -static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - u32 seg; - - seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, order); - if (seg == -1) - return -1; - - if (mlx4_table_get_range(dev, &mr_table->mtt_table, seg, - seg + (1 << order) - 1)) { - mlx4_buddy_free(&mr_table->mtt_buddy, seg, order); - return -1; - } - - return seg; -} - -int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, - struct mlx4_mtt *mtt) -{ - int i; - - if (!npages) { - mtt->order = -1; - mtt->page_shift = MLX4_ICM_PAGE_SHIFT; - return 0; - } else - mtt->page_shift = page_shift; - - for (mtt->order = 0, i = MLX4_MTT_ENTRY_PER_SEG; i < npages; i <<= 1) - ++mtt->order; - - mtt->first_seg = mlx4_alloc_mtt_range(dev, mtt->order); - if (mtt->first_seg == -1) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_mtt_init); - -void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - if (mtt->order < 0) - return; - - mlx4_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order); - mlx4_table_put_range(dev, &mr_table->mtt_table, mtt->first_seg, - mtt->first_seg + (1 << mtt->order) - 1); -} -EXPORT_SYMBOL_GPL(mlx4_mtt_cleanup); - -u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt) -{ - return (u64) mtt->first_seg * dev->caps.mtt_entry_sz; -} -EXPORT_SYMBOL_GPL(mlx4_mtt_addr); - -static u32 hw_index_to_key(u32 ind) -{ - return (ind >> 24) | (ind << 8); -} - -static u32 key_to_hw_index(u32 key) -{ - return (key << 24) | (key >> 8); -} - -static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int mpt_index) -{ - return mlx4_cmd(dev, mailbox->dma, mpt_index, 0, MLX4_CMD_SW2HW_MPT, - MLX4_CMD_TIME_CLASS_B); -} - -static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int mpt_index) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index, - !mailbox, MLX4_CMD_HW2SW_MPT, MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, - int npages, int page_shift, struct mlx4_mr *mr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u32 index; - int err; - - index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); - if (index == -1) { - err = -ENOMEM; - goto err; - } - - mr->iova = iova; - mr->size = size; - mr->pd = pd; - mr->access = access; - mr->enabled = 0; - mr->key = hw_index_to_key(index); - - err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); - if (err) - goto err_index; - - return 0; - -err_index: - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); - -err: - kfree(mr); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_mr_alloc); - -void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - if (mr->enabled) { - err = mlx4_HW2SW_MPT(dev, NULL, - key_to_hw_index(mr->key) & - (dev->caps.num_mpts - 1)); - if (err) - mlx4_warn(dev, "HW2SW_MPT failed (%d)\n", err); - } - - mlx4_mtt_cleanup(dev, &mr->mtt); - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, key_to_hw_index(mr->key)); -} -EXPORT_SYMBOL_GPL(mlx4_mr_free); - -int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mpt_entry *mpt_entry; - int err; - - err = mlx4_table_get(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); - if (err) - return err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_table; - } - mpt_entry = mailbox->buf; - - memset(mpt_entry, 0, sizeof *mpt_entry); - - mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS | - MLX4_MPT_FLAG_MIO | - MLX4_MPT_FLAG_REGION | - mr->access); - if (mr->mtt.order < 0) - mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); - - mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); - mpt_entry->pd = cpu_to_be32(mr->pd); - mpt_entry->start = cpu_to_be64(mr->iova); - mpt_entry->length = cpu_to_be64(mr->size); - mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); - mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); - - err = mlx4_SW2HW_MPT(dev, mailbox, - key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); - if (err) { - mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); - goto err_cmd; - } - - mr->enabled = 1; - - mlx4_free_cmd_mailbox(dev, mailbox); - - return 0; - -err_cmd: - mlx4_free_cmd_mailbox(dev, mailbox); - -err_table: - mlx4_table_put(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_mr_enable); - -static int mlx4_WRITE_MTT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int num_mtt) -{ - return mlx4_cmd(dev, mailbox->dma, num_mtt, 0, MLX4_CMD_WRITE_MTT, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - int start_index, int npages, u64 *page_list) -{ - struct mlx4_cmd_mailbox *mailbox; - __be64 *mtt_entry; - int i; - int err = 0; - - if (mtt->order < 0) - return -EINVAL; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - mtt_entry = mailbox->buf; - - while (npages > 0) { - mtt_entry[0] = cpu_to_be64(mlx4_mtt_addr(dev, mtt) + start_index * 8); - mtt_entry[1] = 0; - - for (i = 0; i < npages && i < MLX4_MAILBOX_SIZE / 8 - 2; ++i) - mtt_entry[i + 2] = cpu_to_be64(page_list[i] | - MLX4_MTT_FLAG_PRESENT); - - /* - * If we have an odd number of entries to write, add - * one more dummy entry for firmware efficiency. - */ - if (i & 1) - mtt_entry[i + 2] = 0; - - err = mlx4_WRITE_MTT(dev, mailbox, (i + 1) & ~1); - if (err) - goto out; - - npages -= i; - start_index += i; - page_list += i; - } - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_write_mtt); - -int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - struct mlx4_buf *buf) -{ - u64 *page_list; - int err; - int i; - - page_list = kmalloc(buf->npages * sizeof *page_list, GFP_KERNEL); - if (!page_list) - return -ENOMEM; - - for (i = 0; i < buf->npages; ++i) - if (buf->nbufs == 1) - page_list[i] = buf->u.direct.map + (i << buf->page_shift); - else - page_list[i] = buf->u.page_list[i].map; - - err = mlx4_write_mtt(dev, mtt, 0, buf->npages, page_list); - - kfree(page_list); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); - -int __devinit mlx4_init_mr_table(struct mlx4_dev *dev) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - int err; - - err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, - ~0, dev->caps.reserved_mrws); - if (err) - return err; - - err = mlx4_buddy_init(&mr_table->mtt_buddy, - ilog2(dev->caps.num_mtt_segs)); - if (err) - goto err_buddy; - - if (dev->caps.reserved_mtts) { - if (mlx4_alloc_mtt_range(dev, ilog2(dev->caps.reserved_mtts)) == -1) { - mlx4_warn(dev, "MTT table of order %d is too small.\n", - mr_table->mtt_buddy.max_order); - err = -ENOMEM; - goto err_reserve_mtts; - } - } - - return 0; - -err_reserve_mtts: - mlx4_buddy_cleanup(&mr_table->mtt_buddy); - -err_buddy: - mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); - - return err; -} - -void mlx4_cleanup_mr_table(struct mlx4_dev *dev) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - mlx4_buddy_cleanup(&mr_table->mtt_buddy); - mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); -} diff --git a/trunk/drivers/net/mlx4/pd.c b/trunk/drivers/net/mlx4/pd.c deleted file mode 100644 index 23dea1ee7750..000000000000 --- a/trunk/drivers/net/mlx4/pd.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. 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 "mlx4.h" -#include "icm.h" - -int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); - if (*pdn == -1) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_pd_alloc); - -void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) -{ - mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn); -} -EXPORT_SYMBOL_GPL(mlx4_pd_free); - -int __devinit mlx4_init_pd_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds, - (1 << 24) - 1, dev->caps.reserved_pds); -} - -void mlx4_cleanup_pd_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); -} - - -int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) -{ - uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap); - if (uar->index == -1) - return -ENOMEM; - - uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_uar_alloc); - -void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar) -{ - mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index); -} -EXPORT_SYMBOL_GPL(mlx4_uar_free); - -int mlx4_init_uar_table(struct mlx4_dev *dev) -{ - return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap, - dev->caps.num_uars, dev->caps.num_uars - 1, - max(128, dev->caps.reserved_uars)); -} - -void mlx4_cleanup_uar_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/profile.c b/trunk/drivers/net/mlx4/profile.c deleted file mode 100644 index 9ca42b213d54..000000000000 --- a/trunk/drivers/net/mlx4/profile.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "fw.h" - -enum { - MLX4_RES_QP, - MLX4_RES_RDMARC, - MLX4_RES_ALTC, - MLX4_RES_AUXC, - MLX4_RES_SRQ, - MLX4_RES_CQ, - MLX4_RES_EQ, - MLX4_RES_DMPT, - MLX4_RES_CMPT, - MLX4_RES_MTT, - MLX4_RES_MCG, - MLX4_RES_NUM -}; - -static const char *res_name[] = { - [MLX4_RES_QP] = "QP", - [MLX4_RES_RDMARC] = "RDMARC", - [MLX4_RES_ALTC] = "ALTC", - [MLX4_RES_AUXC] = "AUXC", - [MLX4_RES_SRQ] = "SRQ", - [MLX4_RES_CQ] = "CQ", - [MLX4_RES_EQ] = "EQ", - [MLX4_RES_DMPT] = "DMPT", - [MLX4_RES_CMPT] = "CMPT", - [MLX4_RES_MTT] = "MTT", - [MLX4_RES_MCG] = "MCG", -}; - -u64 mlx4_make_profile(struct mlx4_dev *dev, - struct mlx4_profile *request, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource { - u64 size; - u64 start; - int type; - int num; - int log_num; - }; - - u64 total_size = 0; - struct mlx4_resource *profile; - struct mlx4_resource tmp; - int i, j; - - profile = kzalloc(MLX4_RES_NUM * sizeof *profile, GFP_KERNEL); - if (!profile) - return -ENOMEM; - - profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz; - profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz; - profile[MLX4_RES_ALTC].size = dev_cap->altc_entry_sz; - profile[MLX4_RES_AUXC].size = dev_cap->aux_entry_sz; - profile[MLX4_RES_SRQ].size = dev_cap->srq_entry_sz; - profile[MLX4_RES_CQ].size = dev_cap->cqc_entry_sz; - profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz; - profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; - profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; - profile[MLX4_RES_MTT].size = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; - profile[MLX4_RES_MCG].size = MLX4_MGM_ENTRY_SIZE; - - profile[MLX4_RES_QP].num = request->num_qp; - profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; - profile[MLX4_RES_ALTC].num = request->num_qp; - profile[MLX4_RES_AUXC].num = request->num_qp; - profile[MLX4_RES_SRQ].num = request->num_srq; - profile[MLX4_RES_CQ].num = request->num_cq; - profile[MLX4_RES_EQ].num = MLX4_NUM_EQ + dev_cap->reserved_eqs; - profile[MLX4_RES_DMPT].num = request->num_mpt; - profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; - profile[MLX4_RES_MTT].num = request->num_mtt; - profile[MLX4_RES_MCG].num = request->num_mcg; - - for (i = 0; i < MLX4_RES_NUM; ++i) { - profile[i].type = i; - profile[i].num = roundup_pow_of_two(profile[i].num); - profile[i].log_num = ilog2(profile[i].num); - profile[i].size *= profile[i].num; - profile[i].size = max(profile[i].size, (u64) PAGE_SIZE); - } - - /* - * Sort the resources in decreasing order of size. Since they - * all have sizes that are powers of 2, we'll be able to keep - * resources aligned to their size and pack them without gaps - * using the sorted order. - */ - for (i = MLX4_RES_NUM; i > 0; --i) - for (j = 1; j < i; ++j) { - if (profile[j].size > profile[j - 1].size) { - tmp = profile[j]; - profile[j] = profile[j - 1]; - profile[j - 1] = tmp; - } - } - - for (i = 0; i < MLX4_RES_NUM; ++i) { - if (profile[i].size) { - profile[i].start = total_size; - total_size += profile[i].size; - } - - if (total_size > dev_cap->max_icm_sz) { - mlx4_err(dev, "Profile requires 0x%llx bytes; " - "won't fit in 0x%llx bytes of context memory.\n", - (unsigned long long) total_size, - (unsigned long long) dev_cap->max_icm_sz); - kfree(profile); - return -ENOMEM; - } - - if (profile[i].size) - mlx4_dbg(dev, " profile[%2d] (%6s): 2^%02d entries @ 0x%10llx, " - "size 0x%10llx\n", - i, res_name[profile[i].type], profile[i].log_num, - (unsigned long long) profile[i].start, - (unsigned long long) profile[i].size); - } - - mlx4_dbg(dev, "HCA context memory: reserving %d KB\n", - (int) (total_size >> 10)); - - for (i = 0; i < MLX4_RES_NUM; ++i) { - switch (profile[i].type) { - case MLX4_RES_QP: - dev->caps.num_qps = profile[i].num; - init_hca->qpc_base = profile[i].start; - init_hca->log_num_qps = profile[i].log_num; - break; - case MLX4_RES_RDMARC: - for (priv->qp_table.rdmarc_shift = 0; - request->num_qp << priv->qp_table.rdmarc_shift < profile[i].num; - ++priv->qp_table.rdmarc_shift) - ; /* nothing */ - dev->caps.max_qp_dest_rdma = 1 << priv->qp_table.rdmarc_shift; - priv->qp_table.rdmarc_base = (u32) profile[i].start; - init_hca->rdmarc_base = profile[i].start; - init_hca->log_rd_per_qp = priv->qp_table.rdmarc_shift; - break; - case MLX4_RES_ALTC: - init_hca->altc_base = profile[i].start; - break; - case MLX4_RES_AUXC: - init_hca->auxc_base = profile[i].start; - break; - case MLX4_RES_SRQ: - dev->caps.num_srqs = profile[i].num; - init_hca->srqc_base = profile[i].start; - init_hca->log_num_srqs = profile[i].log_num; - break; - case MLX4_RES_CQ: - dev->caps.num_cqs = profile[i].num; - init_hca->cqc_base = profile[i].start; - init_hca->log_num_cqs = profile[i].log_num; - break; - case MLX4_RES_EQ: - dev->caps.num_eqs = profile[i].num; - init_hca->eqc_base = profile[i].start; - init_hca->log_num_eqs = profile[i].log_num; - break; - case MLX4_RES_DMPT: - dev->caps.num_mpts = profile[i].num; - priv->mr_table.mpt_base = profile[i].start; - init_hca->dmpt_base = profile[i].start; - init_hca->log_mpt_sz = profile[i].log_num; - break; - case MLX4_RES_CMPT: - init_hca->cmpt_base = profile[i].start; - break; - case MLX4_RES_MTT: - dev->caps.num_mtt_segs = profile[i].num; - priv->mr_table.mtt_base = profile[i].start; - init_hca->mtt_base = profile[i].start; - break; - case MLX4_RES_MCG: - dev->caps.num_mgms = profile[i].num >> 1; - dev->caps.num_amgms = profile[i].num >> 1; - init_hca->mc_base = profile[i].start; - init_hca->log_mc_entry_sz = ilog2(MLX4_MGM_ENTRY_SIZE); - init_hca->log_mc_table_sz = profile[i].log_num; - init_hca->log_mc_hash_sz = profile[i].log_num - 1; - break; - default: - break; - } - } - - /* - * PDs don't take any HCA memory, but we assign them as part - * of the HCA profile anyway. - */ - dev->caps.num_pds = MLX4_NUM_PDS; - - kfree(profile); - return total_size; -} diff --git a/trunk/drivers/net/mlx4/qp.c b/trunk/drivers/net/mlx4/qp.c deleted file mode 100644 index 7f8b7d55b6e1..000000000000 --- a/trunk/drivers/net/mlx4/qp.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, 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 "mlx4.h" -#include "icm.h" - -void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - struct mlx4_qp *qp; - - spin_lock(&qp_table->lock); - - qp = __mlx4_qp_lookup(dev, qpn); - if (qp) - atomic_inc(&qp->refcount); - - spin_unlock(&qp_table->lock); - - if (!qp) { - mlx4_warn(dev, "Async event for bogus QP %08x\n", qpn); - return; - } - - qp->event(qp, event_type); - - if (atomic_dec_and_test(&qp->refcount)) - complete(&qp->free); -} - -int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, - struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar, - int sqd_event, struct mlx4_qp *qp) -{ - static const u16 op[MLX4_QP_NUM_STATE][MLX4_QP_NUM_STATE] = { - [MLX4_QP_STATE_RST] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_INIT] = MLX4_CMD_RST2INIT_QP, - }, - [MLX4_QP_STATE_INIT] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_INIT] = MLX4_CMD_INIT2INIT_QP, - [MLX4_QP_STATE_RTR] = MLX4_CMD_INIT2RTR_QP, - }, - [MLX4_QP_STATE_RTR] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_RTR2RTS_QP, - }, - [MLX4_QP_STATE_RTS] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_RTS2RTS_QP, - [MLX4_QP_STATE_SQD] = MLX4_CMD_RTS2SQD_QP, - }, - [MLX4_QP_STATE_SQD] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_SQD2RTS_QP, - [MLX4_QP_STATE_SQD] = MLX4_CMD_SQD2SQD_QP, - }, - [MLX4_QP_STATE_SQER] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_SQERR2RTS_QP, - }, - [MLX4_QP_STATE_ERR] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - } - }; - - struct mlx4_cmd_mailbox *mailbox; - int ret = 0; - - if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - new_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - !op[cur_state][new_state]) - return -EINVAL; - - if (op[cur_state][new_state] == MLX4_CMD_2RST_QP) - return mlx4_cmd(dev, 0, qp->qpn, 2, - MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A); - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - if (cur_state == MLX4_QP_STATE_RST && new_state == MLX4_QP_STATE_INIT) { - u64 mtt_addr = mlx4_mtt_addr(dev, mtt); - context->mtt_base_addr_h = mtt_addr >> 32; - context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - } - - *(__be32 *) mailbox->buf = cpu_to_be32(optpar); - memcpy(mailbox->buf + 8, context, sizeof *context); - - ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn = - cpu_to_be32(qp->qpn); - - ret = mlx4_cmd(dev, mailbox->dma, qp->qpn | (!!sqd_event << 31), - new_state == MLX4_QP_STATE_RST ? 2 : 0, - op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C); - - mlx4_free_cmd_mailbox(dev, mailbox); - return ret; -} -EXPORT_SYMBOL_GPL(mlx4_qp_modify); - -int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - int err; - - if (sqpn) - qp->qpn = sqpn; - else { - qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap); - if (qp->qpn == -1) - return -ENOMEM; - } - - err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &qp_table->auxc_table, qp->qpn); - if (err) - goto err_put_qp; - - err = mlx4_table_get(dev, &qp_table->altc_table, qp->qpn); - if (err) - goto err_put_auxc; - - err = mlx4_table_get(dev, &qp_table->rdmarc_table, qp->qpn); - if (err) - goto err_put_altc; - - err = mlx4_table_get(dev, &qp_table->cmpt_table, qp->qpn); - if (err) - goto err_put_rdmarc; - - spin_lock_irq(&qp_table->lock); - err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp); - spin_unlock_irq(&qp_table->lock); - if (err) - goto err_put_cmpt; - - atomic_set(&qp->refcount, 1); - init_completion(&qp->free); - - return 0; - -err_put_cmpt: - mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); - -err_put_rdmarc: - mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); - -err_put_altc: - mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); - -err_put_auxc: - mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); - -err_put_qp: - mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - -err_out: - if (!sqpn) - mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_qp_alloc); - -void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - unsigned long flags; - - spin_lock_irqsave(&qp_table->lock, flags); - radix_tree_delete(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1)); - spin_unlock_irqrestore(&qp_table->lock, flags); -} -EXPORT_SYMBOL_GPL(mlx4_qp_remove); - -void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - - if (atomic_dec_and_test(&qp->refcount)) - complete(&qp->free); - wait_for_completion(&qp->free); - - mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); - mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - - mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); -} -EXPORT_SYMBOL_GPL(mlx4_qp_free); - -static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn) -{ - return mlx4_cmd(dev, 0, base_qpn, 0, MLX4_CMD_CONF_SPECIAL_QP, - MLX4_CMD_TIME_CLASS_B); -} - -int __devinit mlx4_init_qp_table(struct mlx4_dev *dev) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - int err; - - spin_lock_init(&qp_table->lock); - INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); - - /* - * We reserve 2 extra QPs per port for the special QPs. The - * block of special QPs must be aligned to a multiple of 8, so - * round up. - */ - dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8); - err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, - (1 << 24) - 1, dev->caps.sqp_start + 8); - if (err) - return err; - - return mlx4_CONF_SPECIAL_QP(dev, dev->caps.sqp_start); -} - -void mlx4_cleanup_qp_table(struct mlx4_dev *dev) -{ - mlx4_CONF_SPECIAL_QP(dev, 0); - mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/reset.c b/trunk/drivers/net/mlx4/reset.c deleted file mode 100644 index 51eef8492e93..000000000000 --- a/trunk/drivers/net/mlx4/reset.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" - -int mlx4_reset(struct mlx4_dev *dev) -{ - void __iomem *reset; - u32 *hca_header = NULL; - int pcie_cap; - u16 devctl; - u16 linkctl; - u16 vendor; - unsigned long end; - u32 sem; - int i; - int err = 0; - -#define MLX4_RESET_BASE 0xf0000 -#define MLX4_RESET_SIZE 0x400 -#define MLX4_SEM_OFFSET 0x3fc -#define MLX4_RESET_OFFSET 0x10 -#define MLX4_RESET_VALUE swab32(1) - -#define MLX4_SEM_TIMEOUT_JIFFIES (10 * HZ) -#define MLX4_RESET_TIMEOUT_JIFFIES (2 * HZ) - - /* - * Reset the chip. This is somewhat ugly because we have to - * save off the PCI header before reset and then restore it - * after the chip reboots. We skip config space offsets 22 - * and 23 since those have a special meaning. - */ - - /* Do we need to save off the full 4K PCI Express header?? */ - hca_header = kmalloc(256, GFP_KERNEL); - if (!hca_header) { - err = -ENOMEM; - mlx4_err(dev, "Couldn't allocate memory to save HCA " - "PCI header, aborting.\n"); - goto out; - } - - pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); - - for (i = 0; i < 64; ++i) { - if (i == 22 || i == 23) - continue; - if (pci_read_config_dword(dev->pdev, i * 4, hca_header + i)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't save HCA " - "PCI header, aborting.\n"); - goto out; - } - } - - reset = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_RESET_BASE, - MLX4_RESET_SIZE); - if (!reset) { - err = -ENOMEM; - mlx4_err(dev, "Couldn't map HCA reset register, aborting.\n"); - goto out; - } - - /* grab HW semaphore to lock out flash updates */ - end = jiffies + MLX4_SEM_TIMEOUT_JIFFIES; - do { - sem = readl(reset + MLX4_SEM_OFFSET); - if (!sem) - break; - - msleep(1); - } while (time_before(jiffies, end)); - - if (sem) { - mlx4_err(dev, "Failed to obtain HW semaphore, aborting\n"); - err = -EAGAIN; - iounmap(reset); - goto out; - } - - /* actually hit reset */ - writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET); - iounmap(reset); - - end = jiffies + MLX4_RESET_TIMEOUT_JIFFIES; - do { - if (!pci_read_config_word(dev->pdev, PCI_VENDOR_ID, &vendor) && - vendor != 0xffff) - break; - - msleep(1); - } while (time_before(jiffies, end)); - - if (vendor == 0xffff) { - err = -ENODEV; - mlx4_err(dev, "PCI device did not come back after reset, " - "aborting.\n"); - goto out; - } - - /* Now restore the PCI headers */ - if (pcie_cap) { - devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4]; - if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_DEVCTL, - devctl)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA PCI Express " - "Device Control register, aborting.\n"); - goto out; - } - linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4]; - if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_LNKCTL, - linkctl)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA PCI Express " - "Link control register, aborting.\n"); - goto out; - } - } - - for (i = 0; i < 16; ++i) { - if (i * 4 == PCI_COMMAND) - continue; - - if (pci_write_config_dword(dev->pdev, i * 4, hca_header[i])) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA reg %x, " - "aborting.\n", i); - goto out; - } - } - - if (pci_write_config_dword(dev->pdev, PCI_COMMAND, - hca_header[PCI_COMMAND / 4])) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA COMMAND, " - "aborting.\n"); - goto out; - } - -out: - kfree(hca_header); - - return err; -} diff --git a/trunk/drivers/net/mlx4/srq.c b/trunk/drivers/net/mlx4/srq.c deleted file mode 100644 index 2134f83aed87..000000000000 --- a/trunk/drivers/net/mlx4/srq.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, 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 "mlx4.h" -#include "icm.h" - -struct mlx4_srq_context { - __be32 state_logsize_srqn; - u8 logstride; - u8 reserved1[3]; - u8 pg_offset; - u8 reserved2[3]; - u32 reserved3; - u8 log_page_size; - u8 reserved4[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 pd; - __be16 limit_watermark; - __be16 wqe_cnt; - u16 reserved5; - __be16 wqe_counter; - u32 reserved6; - __be64 db_rec_addr; -}; - -void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - struct mlx4_srq *srq; - - spin_lock(&srq_table->lock); - - srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1)); - if (srq) - atomic_inc(&srq->refcount); - - spin_unlock(&srq_table->lock); - - if (!srq) { - mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn); - return; - } - - srq->event(srq, event_type); - - if (atomic_dec_and_test(&srq->refcount)) - complete(&srq->free); -} - -static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int srq_num) -{ - return mlx4_cmd(dev, mailbox->dma, srq_num, 0, MLX4_CMD_SW2HW_SRQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int srq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num, - mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark) -{ - return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, - u64 db_rec, struct mlx4_srq *srq) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_srq_context *srq_context; - u64 mtt_addr; - int err; - - srq->srqn = mlx4_bitmap_alloc(&srq_table->bitmap); - if (srq->srqn == -1) - return -ENOMEM; - - err = mlx4_table_get(dev, &srq_table->table, srq->srqn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &srq_table->cmpt_table, srq->srqn); - if (err) - goto err_put; - - spin_lock_irq(&srq_table->lock); - err = radix_tree_insert(&srq_table->tree, srq->srqn, srq); - spin_unlock_irq(&srq_table->lock); - if (err) - goto err_cmpt_put; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_radix; - } - - srq_context = mailbox->buf; - memset(srq_context, 0, sizeof *srq_context); - - srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) | - srq->srqn); - srq_context->logstride = srq->wqe_shift - 4; - srq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, mtt); - srq_context->mtt_base_addr_h = mtt_addr >> 32; - srq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - srq_context->pd = cpu_to_be32(pdn); - srq_context->db_rec_addr = cpu_to_be64(db_rec); - - err = mlx4_SW2HW_SRQ(dev, mailbox, srq->srqn); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - goto err_radix; - - atomic_set(&srq->refcount, 1); - init_completion(&srq->free); - - return 0; - -err_radix: - spin_lock_irq(&srq_table->lock); - radix_tree_delete(&srq_table->tree, srq->srqn); - spin_unlock_irq(&srq_table->lock); - -err_cmpt_put: - mlx4_table_put(dev, &srq_table->cmpt_table, srq->srqn); - -err_put: - mlx4_table_put(dev, &srq_table->table, srq->srqn); - -err_out: - mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_srq_alloc); - -void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - int err; - - err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn); - if (err) - mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn); - - spin_lock_irq(&srq_table->lock); - radix_tree_delete(&srq_table->tree, srq->srqn); - spin_unlock_irq(&srq_table->lock); - - if (atomic_dec_and_test(&srq->refcount)) - complete(&srq->free); - wait_for_completion(&srq->free); - - mlx4_table_put(dev, &srq_table->table, srq->srqn); - mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); -} -EXPORT_SYMBOL_GPL(mlx4_srq_free); - -int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark) -{ - return mlx4_ARM_SRQ(dev, srq->srqn, limit_watermark); -} -EXPORT_SYMBOL_GPL(mlx4_srq_arm); - -int __devinit mlx4_init_srq_table(struct mlx4_dev *dev) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - int err; - - spin_lock_init(&srq_table->lock); - INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC); - - err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs, - dev->caps.num_srqs - 1, dev->caps.reserved_srqs); - if (err) - return err; - - return 0; -} - -void mlx4_cleanup_srq_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap); -} diff --git a/trunk/drivers/net/natsemi.c b/trunk/drivers/net/natsemi.c index 4cf0d3fcb519..223e0e6264ba 100644 --- a/trunk/drivers/net/natsemi.c +++ b/trunk/drivers/net/natsemi.c @@ -131,6 +131,7 @@ static const char version[] __devinitdata = KERN_INFO DRV_NAME " dp8381x driver, version " DRV_VERSION ", " DRV_RELDATE "\n" KERN_INFO " originally by Donald Becker \n" + KERN_INFO " http://www.scyld.com/network/natsemi.html\n" KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; MODULE_AUTHOR("Donald Becker "); diff --git a/trunk/drivers/net/ne2k-pci.c b/trunk/drivers/net/ne2k-pci.c index 995c0a5d4066..589785d1e762 100644 --- a/trunk/drivers/net/ne2k-pci.c +++ b/trunk/drivers/net/ne2k-pci.c @@ -63,7 +63,8 @@ static int options[MAX_UNITS]; /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n"; +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n" +KERN_INFO " http://www.scyld.com/network/ne2k-pci.html\n"; #if defined(__powerpc__) #define inl_le(addr) le32_to_cpu(inl(addr)) diff --git a/trunk/drivers/net/pcmcia/ibmtr_cs.c b/trunk/drivers/net/pcmcia/ibmtr_cs.c index 4ecb8ca5a992..1060154ae750 100644 --- a/trunk/drivers/net/pcmcia/ibmtr_cs.c +++ b/trunk/drivers/net/pcmcia/ibmtr_cs.c @@ -189,20 +189,16 @@ static void ibmtr_detach(struct pcmcia_device *link) { struct ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - struct tok_info *ti = netdev_priv(dev); DEBUG(0, "ibmtr_detach(0x%p)\n", link); - - /* - * When the card removal interrupt hits tok_interrupt(), - * bail out early, so we don't crash the machine - */ - ti->sram_phys |= 1; if (link->dev_node) unregister_netdev(dev); - - del_timer_sync(&(ti->tr_timer)); + + { + struct tok_info *ti = netdev_priv(dev); + del_timer_sync(&(ti->tr_timer)); + } ibmtr_release(link); diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index c0d3101eb6a0..f994f129f3d8 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -3,7 +3,6 @@ # menu "PHY device support" - depends on !S390 config PHYLIB tristate "PHY Device support and infrastructure" diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index f71dab347667..eed433d6056a 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -662,10 +662,10 @@ int phy_stop_interrupts(struct phy_device *phydev) phy_error(phydev); /* - * Finish any pending work; we might have been scheduled to be called - * from keventd ourselves, but cancel_work_sync() handles that. + * Finish any pending work; we might have been scheduled + * to be called from keventd ourselves, though. */ - cancel_work_sync(&phydev->phy_queue); + run_scheduled_work(&phydev->phy_queue); free_irq(phydev->irq, phydev); diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index e0489578945d..b07da1054add 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -3594,9 +3594,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->duplex = -1; skge->speed = -1; skge->advertising = skge_supported_modes(hw); - - if (pci_wake_enabled(hw->pdev)) - skge->wol = wol_supported(hw) & WAKE_MAGIC; + skge->wol = pci_wake_enabled(hw->pdev) ? wol_supported(hw) : 0; hw->dev[port] = dev; diff --git a/trunk/drivers/net/sundance.c b/trunk/drivers/net/sundance.c index e1f912d04043..f51ba31970aa 100644 --- a/trunk/drivers/net/sundance.c +++ b/trunk/drivers/net/sundance.c @@ -110,7 +110,8 @@ static char *media[MAX_UNITS]; /* These identify the driver base version and may not be removed. */ static char version[] = -KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"; +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"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Sundance Alta Ethernet driver"); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 923b9c725cc3..e5e901ecd808 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -3716,8 +3716,10 @@ static void tg3_reset_task(struct work_struct *work) unsigned int restart_timer; tg3_full_lock(tp, 0); + tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; if (!netif_running(tp->dev)) { + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); return; } @@ -3748,6 +3750,8 @@ static void tg3_reset_task(struct work_struct *work) mod_timer(&tp->timer, jiffies + 1); out: + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; + tg3_full_unlock(tp); } @@ -7386,7 +7390,12 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - cancel_work_sync(&tp->reset_task); + /* Calling flush_scheduled_work() may deadlock because + * linkwatch_event() may be on the workqueue and it will try to get + * the rtnl_lock which we are holding. + */ + while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) + msleep(1); netif_stop_queue(dev); diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index bd9f4f428e5b..4d334cf5a243 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2228,7 +2228,7 @@ struct tg3 { #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 - +#define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_SUPPORT_MSI 0x20000000 diff --git a/trunk/drivers/net/tulip/interrupt.c b/trunk/drivers/net/tulip/interrupt.c index ea896777bcaf..9b08afbd1f65 100644 --- a/trunk/drivers/net/tulip/interrupt.c +++ b/trunk/drivers/net/tulip/interrupt.c @@ -269,7 +269,7 @@ int tulip_poll(struct net_device *dev, int *budget) This would turn on IM for devices that is not contributing to backlog congestion with unnecessary latency. - We monitor the device RX-ring and have: + We monitor the the device RX-ring and have: HW Interrupt Mitigation either ON or OFF. diff --git a/trunk/drivers/net/tulip/winbond-840.c b/trunk/drivers/net/tulip/winbond-840.c index 38f3b99716b8..fa440706fb4a 100644 --- a/trunk/drivers/net/tulip/winbond-840.c +++ b/trunk/drivers/net/tulip/winbond-840.c @@ -1021,7 +1021,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_ring[entry].length |= DescEndRing; /* Now acquire the irq spinlock. - * The difficult race is the ordering between + * The difficult race is the the ordering between * increasing np->cur_tx and setting DescOwned: * - if np->cur_tx is increased first the interrupt * handler could consider the packet as transmitted diff --git a/trunk/drivers/net/tulip/xircom_cb.c b/trunk/drivers/net/tulip/xircom_cb.c index 2470b1ee33c0..985a1810ca59 100644 --- a/trunk/drivers/net/tulip/xircom_cb.c +++ b/trunk/drivers/net/tulip/xircom_cb.c @@ -1043,7 +1043,7 @@ static int enable_promisc(struct xircom_private *card) /* -link_status() checks the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what. +link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what. Must be called in locked state with interrupts disabled */ diff --git a/trunk/drivers/net/typhoon.c b/trunk/drivers/net/typhoon.c index f72573594121..f2dd7763cd0b 100644 --- a/trunk/drivers/net/typhoon.c +++ b/trunk/drivers/net/typhoon.c @@ -639,7 +639,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd, typhoon_inc_cmd_index(&ring->lastWrite, num_cmd); - /* "I feel a presence... another warrior is on the mesa." + /* "I feel a presence... another warrior is on the the mesa." */ wmb(); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); diff --git a/trunk/drivers/net/ucc_geth.c b/trunk/drivers/net/ucc_geth.c index 0f667652fda9..d7aff8189377 100644 --- a/trunk/drivers/net/ucc_geth.c +++ b/trunk/drivers/net/ucc_geth.c @@ -293,7 +293,7 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth, else { init_enet_offset = qe_muram_alloc(thread_size, thread_alignment); - if (IS_ERR_VALUE(init_enet_offset)) { + if (IS_MURAM_ERR(init_enet_offset)) { ugeth_err ("fill_init_enet_entries: Can not allocate DPRAM memory."); qe_put_snum((u8) snum); @@ -2594,7 +2594,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->tx_bd_ring_offset[j] = qe_muram_alloc(length, UCC_GETH_TX_BD_RING_ALIGNMENT); - if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j])) + 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]); @@ -2629,7 +2629,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->rx_bd_ring_offset[j] = qe_muram_alloc(length, UCC_GETH_RX_BD_RING_ALIGNMENT); - if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j])) + 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]); @@ -2713,7 +2713,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->tx_glbl_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) { + if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", __FUNCTION__); @@ -2735,7 +2735,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_thread_data_tx) + 32 * (numThreadsTxNumerical == 1), UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) { + if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", __FUNCTION__); @@ -2763,7 +2763,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(ug_info->numQueuesTx * sizeof(struct ucc_geth_send_queue_qd), UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) { + 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__); @@ -2806,7 +2806,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->scheduler_offset = qe_muram_alloc(sizeof(struct ucc_geth_scheduler), UCC_GETH_SCHEDULER_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->scheduler_offset)) { + if (IS_MURAM_ERR(ugeth->scheduler_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_scheduler.", __FUNCTION__); @@ -2854,7 +2854,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof (struct ucc_geth_tx_firmware_statistics_pram), UCC_GETH_TX_STATISTICS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) { + 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__); @@ -2893,7 +2893,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->rx_glbl_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) { + if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", __FUNCTION__); @@ -2914,7 +2914,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(numThreadsRxNumerical * sizeof(struct ucc_geth_thread_data_rx), UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) { + if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", __FUNCTION__); @@ -2937,7 +2937,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof (struct ucc_geth_rx_firmware_statistics_pram), UCC_GETH_RX_STATISTICS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) { + 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__); @@ -2959,7 +2959,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(ug_info->numQueuesRx * sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) { + 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__); @@ -3027,7 +3027,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) (sizeof(struct ucc_geth_rx_bd_queues_entry) + sizeof(struct ucc_geth_rx_prefetched_bds)), UCC_GETH_RX_BD_QUEUES_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) { + 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__); @@ -3116,7 +3116,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth->exf_glbl_param_offset = qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); - if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) { + if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for" " p_exf_glbl_param.", __FUNCTION__); @@ -3258,7 +3258,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Allocate InitEnet command parameter structure */ init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); - if (IS_ERR_VALUE(init_enet_pram_offset)) { + if (IS_MURAM_ERR(init_enet_pram_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", __FUNCTION__); diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index e3f5bb0fe603..e273347dc606 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -3,7 +3,6 @@ # menu "Wireless LAN" - depends on !S390 config WLAN_PRE80211 bool "Wireless LAN (pre-802.11)" diff --git a/trunk/drivers/net/wireless/airport.c b/trunk/drivers/net/wireless/airport.c index 7d5b8c2cc614..38fac3bbcd82 100644 --- a/trunk/drivers/net/wireless/airport.c +++ b/trunk/drivers/net/wireless/airport.c @@ -149,7 +149,7 @@ static int airport_hard_reset(struct orinoco_private *priv) /* Vitally important. If we don't do this it seems we get an * interrupt somewhere during the power cycle, since * hw_unavailable is already set it doesn't get ACKed, we get - * into an interrupt loop and the PMU decides to turn us + * into an interrupt loop and the the PMU decides to turn us * off. */ disable_irq(dev->irq); diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h index 10e07e865426..f8483c179e4c 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -658,6 +658,12 @@ struct bcm43xx_pio { #define BCM43xx_MAX_80211_CORES 2 +#ifdef CONFIG_BCM947XX +#define core_offset(bcm) (bcm)->current_core_offset +#else +#define core_offset(bcm) 0 +#endif + /* Generic information about a core. */ struct bcm43xx_coreinfo { u8 available:1, @@ -783,6 +789,10 @@ struct bcm43xx_private { /* The currently active core. */ struct bcm43xx_coreinfo *current_core; +#ifdef CONFIG_BCM947XX + /** current core memory offset */ + u32 current_core_offset; +#endif struct bcm43xx_coreinfo *active_80211_core; /* coreinfo structs for all possible cores follow. * Note that a core might not exist. @@ -933,25 +943,25 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, static inline u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) { - return ioread16(bcm->mmio_addr + offset); + return ioread16(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) { - iowrite16(value, bcm->mmio_addr + offset); + iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); } static inline u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) { - return ioread32(bcm->mmio_addr + offset); + return ioread32(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) { - iowrite32(value, bcm->mmio_addr + offset); + iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); } static inline diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 1f7731fcfbd5..e3d2e61a31ee 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -660,6 +660,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, ring->routing = BCM43xx_DMA32_CLIENTTRANS; if (dma64) ring->routing = BCM43xx_DMA64_CLIENTTRANS; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS; +#endif ring->bcm = bcm; ring->nr_slots = nr_slots; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ef6b253a92ce..5e96bca6730a 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -61,6 +61,10 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_BCM947XX +extern char *nvram_get(char *name); +#endif + #if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); @@ -138,6 +142,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple fi { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 43XG 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif { 0 }, }; MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); @@ -778,6 +786,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) { u16 value; u16 *sprom; +#ifdef CONFIG_BCM947XX + char *c; +#endif sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), GFP_KERNEL); @@ -785,7 +796,28 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) printk(KERN_ERR PFX "sprom_extract OOM\n"); return -ENOMEM; } +#ifdef CONFIG_BCM947XX + sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2")); + sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags")); + + if ((c = nvram_get("il0macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR])); + + if ((c = nvram_get("et1macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR])); + + sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0")); + sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1")); + sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2")); + + sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0")); + sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1")); + sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2")); + + sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); +#else bcm43xx_sprom_read(bcm, sprom); +#endif /* boardflags2 */ value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; @@ -1193,6 +1225,12 @@ static int _switch_core(struct bcm43xx_private *bcm, int core) goto error; udelay(10); } +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; +#endif return 0; error: @@ -1349,6 +1387,19 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) if ((bcm43xx_core_enabled(bcm)) && !bcm43xx_using_pio(bcm)) { +//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? +#if 0 +#ifndef CONFIG_BCM947XX + /* reset all used DMA controllers. */ + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + if (bcm->current_core->rev < 5) + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); +#endif +#endif } if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, @@ -2089,11 +2140,32 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) return err; } +#ifdef CONFIG_BCM947XX +static struct pci_device_id bcm43xx_47xx_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, + { 0 } +}; +#endif + static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) { int err; bcm->irq = bcm->pci_dev->irq; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) { + struct pci_dev *d; + struct pci_device_id *id; + for (id = bcm43xx_47xx_ids; id->vendor; id++) { + d = pci_get_device(id->vendor, id->device, NULL); + if (d != NULL) { + bcm->irq = d->irq; + pci_dev_put(d); + break; + } + } + } +#endif err = request_irq(bcm->irq, bcm43xx_interrupt_handler, IRQF_SHARED, KBUILD_MODNAME, bcm); if (err) @@ -2573,6 +2645,10 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) chip_id_16 = 0x4610; else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) chip_id_16 = 0x4710; +#ifdef CONFIG_BCM947XX + else if ((pci_device >= 0x4320) && (pci_device <= 0x4325)) + chip_id_16 = 0x4309; +#endif else { printk(KERN_ERR PFX "Could not determine Chip ID\n"); return -ENODEV; @@ -4068,6 +4144,11 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, struct bcm43xx_private *bcm; int err; +#ifdef CONFIG_BCM947XX + if ((pdev->bus->number == 0) && (pdev->device != 0x0800)) + return -ENODEV; +#endif + #ifdef DEBUG_SINGLE_DEVICE_ONLY if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) return -ENODEV; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h index c8f3c532bab5..f76357178e4d 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -33,6 +33,25 @@ #include "bcm43xx.h" +#ifdef CONFIG_BCM947XX +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) + +static inline void e_aton(char *str, char *dest) +{ + int i = 0; + u16 *d = (u16 *) dest; + + for (;;) { + dest[i++] = (char) simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; + } + for (i = 0; i < 3; i++) + d[i] = cpu_to_be16(d[i]); +} +#endif + #define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] #define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) /* Magic helper macro to pad structures. Ignore those above. It's magic. */ diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 283be4a70524..841b3c136ad9 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -3054,7 +3054,7 @@ static const iw_handler prism54_handler[] = { (iw_handler) prism54_set_wap, /* SIOCSIWAP */ (iw_handler) prism54_get_wap, /* SIOCGIWAP */ (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST deprecated */ + (iw_handler) NULL, /* SIOCGIWAPLIST depreciated */ (iw_handler) prism54_set_scan, /* SIOCSIWSCAN */ (iw_handler) prism54_get_scan, /* SIOCGIWSCAN */ (iw_handler) prism54_set_essid, /* SIOCSIWESSID */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.c b/trunk/drivers/net/wireless/prism54/islpci_dev.c index 084795355b74..a037b11dac9d 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.c +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.c @@ -115,7 +115,7 @@ isl_upload_firmware(islpci_private *priv) ISL38XX_MEMORY_WINDOW_SIZE : fw_len; u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; - /* set the card's base address for writing the data */ + /* set the cards base address for writting the data */ isl38xx_w32_flush(device_base, reg, ISL38XX_DIR_MEM_BASE_REG); wmb(); /* be paranoid */ diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c index 5740d4d4267c..67b867f837ca 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.c +++ b/trunk/drivers/net/wireless/wavelan_cs.c @@ -176,7 +176,7 @@ psa_write(struct net_device * dev, volatile u_char __iomem *verify = lp->mem + PSA_ADDR + (psaoff(0, psa_comp_number) << 1); - /* Authorize writing to PSA */ + /* Authorize writting to PSA */ hacr_write(base, HACR_PWR_STAT | HACR_ROM_WEN); while(n-- > 0) @@ -1676,7 +1676,7 @@ wv_set_frequency(u_long base, /* i/o port of the card */ fee_write(base, 0x60, dac, 2); - /* We now should verify here that the EEprom writing was ok */ + /* We now should verify here that the EEprom writting was ok */ /* ReRead the first area */ fee_read(base, 0x00, diff --git a/trunk/drivers/net/wireless/wavelan_cs.p.h b/trunk/drivers/net/wireless/wavelan_cs.p.h index 4b9de0093a7b..4d1c4905c749 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.p.h +++ b/trunk/drivers/net/wireless/wavelan_cs.p.h @@ -120,7 +120,7 @@ * the Wavelan itself (NCR -> AT&T -> Lucent). * * All started with Anders Klemets , - * writing a Wavelan ISA driver for the MACH microkernel. Girish + * writting a Wavelan ISA driver for the MACH microkernel. Girish * Welling had also worked on it. * Keith Moore modify this for the Pcmcia hardware. * diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 8459549d0cee..e04cffc8adf3 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -40,7 +40,6 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 }, @@ -68,11 +67,8 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, - { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, {} }; diff --git a/trunk/drivers/net/yellowfin.c b/trunk/drivers/net/yellowfin.c index f2a90a7fa2d6..3f4a7cf9efea 100644 --- a/trunk/drivers/net/yellowfin.c +++ b/trunk/drivers/net/yellowfin.c @@ -109,6 +109,7 @@ static int gx_fix; /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker \n" +KERN_INFO " http://www.scyld.com/network/yellowfin.html\n" KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); diff --git a/trunk/drivers/parport/Kconfig b/trunk/drivers/parport/Kconfig index f46c69e4ed82..36c6a1bfe558 100644 --- a/trunk/drivers/parport/Kconfig +++ b/trunk/drivers/parport/Kconfig @@ -6,7 +6,6 @@ # menu "Parallel port support" - depends on HAS_IOMEM config PARPORT tristate "Parallel port support" diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 8e58ea3d95c0..3bb7739d26a5 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -119,7 +119,7 @@ static inline int pci_create_newid_file(struct pci_driver *drv) * system is in its list of supported devices. Returns the matching * pci_device_id structure or %NULL if there is no match. * - * Deprecated, don't use this as it will not catch any dynamic ids + * Depreciated, don't use this as it will not catch any dynamic ids * that a driver might want to check for. */ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, diff --git a/trunk/drivers/pnp/Kconfig b/trunk/drivers/pnp/Kconfig index 1959cef8e9de..c5143201419a 100644 --- a/trunk/drivers/pnp/Kconfig +++ b/trunk/drivers/pnp/Kconfig @@ -3,7 +3,6 @@ # menu "Plug and Play support" - depends on HAS_IOMEM config PNP bool "Plug and Play support" diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index ad445d5e58c7..5e439836db2d 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -3,7 +3,6 @@ # menu "Real Time Clock" - depends on !S390 config RTC_LIB tristate @@ -99,7 +98,7 @@ config RTC_INTF_DEV_UIE_EMUL bool "RTC UIE emulation on dev interface" depends on RTC_INTF_DEV help - Provides an emulation for RTC_UIE if the underlying rtc chip + Provides an emulation for RTC_UIE if the underlaying rtc chip driver does not expose RTC_UIE ioctls. Those requests generate once-per-second update interrupts, used for synchronization. @@ -397,7 +396,7 @@ config RTC_DRV_BFIN config RTC_DRV_RS5C313 tristate "Ricoh RS5C313" - depends on RTC_CLASS && SH_LANDISK + depends on RTC_CLASS && BROKEN help If you say yes here you get support for the Ricoh RS5C313 RTC chips. diff --git a/trunk/drivers/rtc/rtc-rs5c313.c b/trunk/drivers/rtc/rtc-rs5c313.c index 66eb133bf5fd..9d6de371495b 100644 --- a/trunk/drivers/rtc/rtc-rs5c313.c +++ b/trunk/drivers/rtc/rtc-rs5c313.c @@ -126,7 +126,7 @@ static void rs5c313_write_data(unsigned char data) static unsigned char rs5c313_read_data(void) { int i; - unsigned char data = 0; + unsigned char data; for (i = 0; i < 8; i++) { ndelay(700); @@ -194,7 +194,7 @@ static void rs5c313_write_reg(unsigned char addr, unsigned char data) return; } -static inline unsigned char rs5c313_read_cntreg(void) +static inline unsigned char rs5c313_read_cntreg(unsigned char addr) { return rs5c313_read_reg(RS5C313_ADDR_CNTREG); } @@ -212,9 +212,7 @@ static inline void rs5c313_write_intintvreg(unsigned char data) static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) { int data; - int cnt; - cnt = 0; while (1) { RS5C313_CEENABLE; /* CE:H */ @@ -227,10 +225,6 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) RS5C313_CEDISABLE; ndelay(700); /* CE:L */ - if (cnt++ > 100) { - dev_err(dev, "%s: timeout error\n", __FUNCTION__); - return -EIO; - } } data = rs5c313_read_reg(RS5C313_ADDR_SEC); @@ -272,9 +266,7 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) { int data; - int cnt; - cnt = 0; /* busy check. */ while (1) { RS5C313_CEENABLE; /* CE:H */ @@ -287,11 +279,6 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) RS5C313_MISCOP; RS5C313_CEDISABLE; ndelay(700); /* CE:L */ - - if (cnt++ > 100) { - dev_err(dev, "%s: timeout error\n", __FUNCTION__); - return -EIO; - } } data = BIN2BCD(tm->tm_sec); @@ -330,7 +317,6 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) static void rs5c313_check_xstp_bit(void) { struct rtc_time tm; - int cnt; RS5C313_CEENABLE; /* CE:H */ if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { @@ -340,16 +326,12 @@ static void rs5c313_check_xstp_bit(void) rs5c313_write_cntreg(0x07); /* busy check. */ - for (cnt = 0; cnt < 100; cnt++) { - if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) - break; + while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY) RS5C313_MISCOP; - } memset(&tm, 0, sizeof(struct rtc_time)); tm.tm_mday = 1; - tm.tm_mon = 1 - 1; - tm.tm_year = 2000 - 1900; + tm.tm_mon = 1; rs5c313_rtc_set_time(NULL, &tm); printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to " @@ -374,7 +356,7 @@ static int rs5c313_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - return 0; + return err; } static int __devexit rs5c313_rtc_remove(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-sh.c b/trunk/drivers/rtc/rtc-sh.c index e0f91dfce0f5..6abf4811958c 100644 --- a/trunk/drivers/rtc/rtc-sh.c +++ b/trunk/drivers/rtc/rtc-sh.c @@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) writeb(tmp, rtc->regbase + RCR1); - rtc_update_irq(rtc->rtc_dev, 1, events); + rtc_update_irq(&rtc->rtc_dev, 1, events); spin_unlock(&rtc->lock); @@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) rtc->rearm_aie = 1; - rtc_update_irq(rtc->rtc_dev, 1, events); + rtc_update_irq(&rtc->rtc_dev, 1, events); } spin_unlock(&rtc->lock); @@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) spin_lock(&rtc->lock); - rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); + rtc_update_irq(&rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); spin_unlock(&rtc->lock); @@ -341,7 +341,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec--; #endif - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, diff --git a/trunk/drivers/s390/char/Kconfig b/trunk/drivers/s390/Kconfig similarity index 59% rename from trunk/drivers/s390/char/Kconfig rename to trunk/drivers/s390/Kconfig index 66102a184322..165af398fdea 100644 --- a/trunk/drivers/s390/char/Kconfig +++ b/trunk/drivers/s390/Kconfig @@ -1,9 +1,69 @@ +config CCW + bool + default y + +source "drivers/block/Kconfig" + +source "drivers/md/Kconfig" + + +menu "Character device drivers" + +config UNIX98_PTYS + bool "Unix98 PTY support" + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx for + masters and /dev/ttyxx for slaves of pseudo terminals. This scheme + has a number of problems. The GNU C library glibc 2.1 and later, + however, supports the Unix98 naming standard: in order to acquire a + pseudo terminal, a process opens /dev/ptmx; the number of the pseudo + terminal is then made available to the process and the pseudo + terminal slave can be accessed as /dev/pts/. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. + + The entries in /dev/pts/ are created on the fly by a virtual + file system; therefore, if you say Y here you should say Y to + "/dev/pts file system for Unix98 PTYs" as well. + + If you want to say Y here, you need to have the C library glibc 2.1 + or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). + Read the instructions in pertaining to + pseudo terminals. It's safe to say N. + +config UNIX98_PTY_COUNT + int "Maximum number of Unix98 PTYs in use (0-2048)" + depends on UNIX98_PTYS + default "256" + help + The maximum number of Unix98 PTYs that can be used at any one time. + The default is 256, and should be enough for desktop systems. Server + machines which support incoming telnet/rlogin/ssh connections and/or + serve several X terminals may want to increase this: every incoming + connection and every xterm uses up one PTY. + + When not in use, each additional set of 256 PTYs occupy + approximately 8 KB of kernel memory on 32-bit architectures. + +config HANGCHECK_TIMER + tristate "Hangcheck timer" + help + The hangcheck-timer module detects when the system has gone + out to lunch past a certain margin. It can reboot the system + or merely print a warning. + +source "drivers/char/watchdog/Kconfig" + comment "S/390 character device drivers" - depends on S390 config TN3270 tristate "Support for locally attached 3270 terminals" - depends on CCW help Include support for IBM 3270 terminals. @@ -28,7 +88,6 @@ config TN3270_CONSOLE config TN3215 bool "Support for 3215 line mode terminal" - depends on CCW help Include support for IBM 3215 line-mode terminals. @@ -40,19 +99,12 @@ config TN3215_CONSOLE Linux system console. config CCW_CONSOLE - bool - depends on TN3215_CONSOLE || TN3270_CONSOLE - default y - -config SCLP - bool "Support for SCLP" - depends on S390 - help - Include support for the SCLP interface to the service element. - + bool + depends on TN3215_CONSOLE || TN3270_CONSOLE + default y + config SCLP_TTY bool "Support for SCLP line mode terminal" - depends on SCLP help Include support for IBM SCLP line-mode terminals. @@ -65,7 +117,6 @@ config SCLP_CONSOLE config SCLP_VT220_TTY bool "Support for SCLP VT220-compatible terminal" - depends on SCLP help Include support for an IBM SCLP VT220-compatible terminal. @@ -78,7 +129,6 @@ config SCLP_VT220_CONSOLE config SCLP_CPI tristate "Control-Program Identification" - depends on SCLP help This option enables the hardware console interface for system identification. This is commonly used for workload management and @@ -90,7 +140,6 @@ config SCLP_CPI config S390_TAPE tristate "S/390 tape device support" - depends on CCW help Select this option if you want to access channel-attached tape devices on IBM S/390 or zSeries. @@ -145,7 +194,6 @@ config VMLOGRDR config VMCP tristate "Support for the z/VM CP interface (VM only)" - depends on S390 help Select this option if you want to be able to interact with the control program on z/VM @@ -159,8 +207,33 @@ config MONREADER config MONWRITER tristate "API for writing z/VM monitor service records" - depends on S390 default "m" help Character device driver for writing z/VM monitor service records +endmenu + +menu "Cryptographic devices" + +config ZCRYPT + tristate "Support for PCI-attached cryptographic adapters" + select ZCRYPT_MONOLITHIC if ZCRYPT="y" + 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). + +endmenu diff --git a/trunk/drivers/s390/block/Kconfig b/trunk/drivers/s390/block/Kconfig index e879b212cf43..b250c5354503 100644 --- a/trunk/drivers/s390/block/Kconfig +++ b/trunk/drivers/s390/block/Kconfig @@ -1,9 +1,11 @@ +if S390 && BLOCK + comment "S/390 block device drivers" - depends on S390 && BLOCK + depends on S390 config BLK_DEV_XPRAM tristate "XPRAM disk support" - depends on S390 && BLOCK + depends on S390 help Select this option if you want to use your expanded storage on S/390 or zSeries as a disk. This is useful as a _fast_ swap device if you @@ -13,13 +15,12 @@ config BLK_DEV_XPRAM config DCSSBLK tristate "DCSSBLK support" - depends on S390 && BLOCK help Support for dcss block device config DASD tristate "Support for DASD devices" - depends on CCW && BLOCK + depends on CCW help Enable this option if you want to access DASDs directly utilizing S/390s channel subsystem commands. This is necessary for running @@ -61,3 +62,5 @@ config DASD_EER This driver provides a character device interface to the DASD extended error reporting. This is only needed if you want to use applications written for the EER facility. + +endif diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index bfeca57098fa..977521013fe8 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -2174,10 +2174,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) return ret; } -static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, - void *rdc_buffer, - int rdc_buffer_size, - char *magic) +struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device, + void *rdc_buffer, + int rdc_buffer_size, char *magic) { struct dasd_ccw_req *cqr; struct ccw1 *ccw; @@ -2220,7 +2219,6 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, dasd_sfree_request(cqr, cqr->device); return ret; } -EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars); static int __init dasd_init(void) diff --git a/trunk/drivers/s390/block/dasd_diag.c b/trunk/drivers/s390/block/dasd_diag.c index eccac1c3b71b..e810e4a44ed4 100644 --- a/trunk/drivers/s390/block/dasd_diag.c +++ b/trunk/drivers/s390/block/dasd_diag.c @@ -50,7 +50,6 @@ struct dasd_diag_private { struct dasd_diag_rw_io iob; struct dasd_diag_init_io iib; blocknum_t pt_block; - struct ccw_dev_id dev_id; }; struct dasd_diag_req { @@ -103,7 +102,7 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize, iib = &private->iib; memset(iib, 0, sizeof (struct dasd_diag_init_io)); - iib->dev_nr = private->dev_id.devno; + iib->dev_nr = _ccw_device_get_device_number(device->cdev); iib->block_size = blocksize; iib->offset = offset; iib->flaga = DASD_DIAG_FLAGA_DEFAULT; @@ -128,7 +127,7 @@ mdsk_term_io(struct dasd_device * device) private = (struct dasd_diag_private *) device->private; iib = &private->iib; memset(iib, 0, sizeof (struct dasd_diag_init_io)); - iib->dev_nr = private->dev_id.devno; + iib->dev_nr = _ccw_device_get_device_number(device->cdev); rc = dia250(iib, TERM_BIO); return rc; } @@ -167,7 +166,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) private = (struct dasd_diag_private *) device->private; dreq = (struct dasd_diag_req *) cqr->data; - private->iob.dev_nr = private->dev_id.devno; + private->iob.dev_nr = _ccw_device_get_device_number(device->cdev); private->iob.key = 0; private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; private->iob.block_count = dreq->block_count; @@ -324,12 +323,11 @@ dasd_diag_check_device(struct dasd_device *device) "memory allocation failed for private data"); return -ENOMEM; } - ccw_device_get_id(device->cdev, &private->dev_id); device->private = (void *) private; } /* Read Device Characteristics */ rdc_data = (void *) &(private->rdc_data); - rdc_data->dev_nr = private->dev_id.devno; + rdc_data->dev_nr = _ccw_device_get_device_number(device->cdev); rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics); rc = diag210((struct diag210 *) rdc_data); diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 418b4e63a4fa..c9583fbc2a7d 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -450,9 +450,9 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) return 0; } -static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, - void *rcd_buffer, - struct ciw *ciw, __u8 lpm) +struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device, + void *rcd_buffer, + struct ciw *ciw, __u8 lpm) { struct dasd_ccw_req *cqr; struct ccw1 *ccw; diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 672eb0a3dd0b..758cfb542865 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -255,7 +255,6 @@ dasd_ioctl_information(struct dasd_device *device, unsigned long flags; int rc; struct ccw_device *cdev; - struct ccw_dev_id dev_id; if (!device->discipline->fill_info) return -EINVAL; @@ -271,9 +270,8 @@ dasd_ioctl_information(struct dasd_device *device, } cdev = device->cdev; - ccw_device_get_id(cdev, &dev_id); - dasd_info->devno = dev_id.devno; + dasd_info->devno = _ccw_device_get_device_number(device->cdev); dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev); dasd_info->cu_type = cdev->id.cu_type; dasd_info->cu_model = cdev->id.cu_model; diff --git a/trunk/drivers/s390/char/monreader.c b/trunk/drivers/s390/char/monreader.c index 67009bfa093e..8df7b1323c05 100644 --- a/trunk/drivers/s390/char/monreader.c +++ b/trunk/drivers/s390/char/monreader.c @@ -97,7 +97,7 @@ static u8 user_data_sever[16] = { * Create the 8 bytes EBCDIC DCSS segment name from * an ASCII name, incl. padding */ -static void dcss_mkname(char *ascii_name, char *ebcdic_name) +static inline void dcss_mkname(char *ascii_name, char *ebcdic_name) { int i; @@ -191,7 +191,7 @@ static inline u32 mon_rec_end(struct mon_msg *monmsg) return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8)); } -static int mon_check_mca(struct mon_msg *monmsg) +static inline int mon_check_mca(struct mon_msg *monmsg) { if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || (mon_rec_start(monmsg) < mon_dcss_start) || @@ -209,8 +209,8 @@ static int mon_check_mca(struct mon_msg *monmsg) return 0; } -static int mon_send_reply(struct mon_msg *monmsg, - struct mon_private *monpriv) +static inline int mon_send_reply(struct mon_msg *monmsg, + struct mon_private *monpriv) { int rc; @@ -236,7 +236,7 @@ static int mon_send_reply(struct mon_msg *monmsg, return 0; } -static void mon_free_mem(struct mon_private *monpriv) +static inline void mon_free_mem(struct mon_private *monpriv) { int i; @@ -246,7 +246,7 @@ static void mon_free_mem(struct mon_private *monpriv) kfree(monpriv); } -static struct mon_private *mon_alloc_mem(void) +static inline struct mon_private *mon_alloc_mem(void) { int i; struct mon_private *monpriv; @@ -307,7 +307,7 @@ static inline void mon_next_mca(struct mon_msg *monmsg) monmsg->pos = 0; } -static struct mon_msg *mon_next_message(struct mon_private *monpriv) +static inline struct mon_msg *mon_next_message(struct mon_private *monpriv) { struct mon_msg *monmsg; diff --git a/trunk/drivers/s390/char/raw3270.c b/trunk/drivers/s390/char/raw3270.c index f6ef90ee3e7d..8facd14adb7c 100644 --- a/trunk/drivers/s390/char/raw3270.c +++ b/trunk/drivers/s390/char/raw3270.c @@ -589,10 +589,9 @@ static int __raw3270_size_device_vm(struct raw3270 *rp) { int rc, model; - struct ccw_dev_id dev_id; - ccw_device_get_id(rp->cdev, &dev_id); - raw3270_init_diag210.vrdcdvno = dev_id.devno; + raw3270_init_diag210.vrdcdvno = + _ccw_device_get_device_number(rp->cdev); raw3270_init_diag210.vrdclen = sizeof(struct diag210); rc = diag210(&raw3270_init_diag210); if (rc) diff --git a/trunk/drivers/s390/char/sclp.h b/trunk/drivers/s390/char/sclp.h index dbb99d1b6f57..87ac4a3ad49d 100644 --- a/trunk/drivers/s390/char/sclp.h +++ b/trunk/drivers/s390/char/sclp.h @@ -132,9 +132,6 @@ int sclp_deactivate(void); int sclp_reactivate(void); int sclp_service_call(sclp_cmdw_t command, void *sccb); -int sclp_sdias_init(void); -void sclp_sdias_exit(void); - /* useful inlines */ /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ diff --git a/trunk/drivers/s390/char/sclp_rw.c b/trunk/drivers/s390/char/sclp_rw.c index d6b06ab81188..bbd5b8b66f42 100644 --- a/trunk/drivers/s390/char/sclp_rw.c +++ b/trunk/drivers/s390/char/sclp_rw.c @@ -23,7 +23,7 @@ /* * The room for the SCCB (only for writing) is not equal to a pages size - * (as it is specified as the maximum size in the SCLP documentation) + * (as it is specified as the maximum size in the the SCLP documentation) * because of the additional data structure described above. */ #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) diff --git a/trunk/drivers/s390/char/sclp_sdias.c b/trunk/drivers/s390/char/sclp_sdias.c index 1c064976b32b..52283daddaef 100644 --- a/trunk/drivers/s390/char/sclp_sdias.c +++ b/trunk/drivers/s390/char/sclp_sdias.c @@ -66,9 +66,9 @@ static DEFINE_MUTEX(sdias_mutex); static void sdias_callback(struct sclp_req *request, void *data) { - struct sdias_sccb *cbsccb; + struct sdias_sccb *sccb; - cbsccb = (struct sdias_sccb *) request->sccb; + sccb = (struct sdias_sccb *) request->sccb; sclp_req_done = 1; wake_up(&sdias_wq); /* Inform caller, that request is complete */ TRACE("callback done\n"); @@ -229,7 +229,7 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) return rc; } -int __init sclp_sdias_init(void) +int __init sdias_init(void) { int rc; @@ -248,7 +248,7 @@ int __init sclp_sdias_init(void) return 0; } -void __exit sclp_sdias_exit(void) +void __exit sdias_exit(void) { debug_unregister(sdias_dbf); sclp_unregister(&sclp_sdias_register); diff --git a/trunk/drivers/s390/char/zcore.c b/trunk/drivers/s390/char/zcore.c index 66eb0688d523..89d439316a53 100644 --- a/trunk/drivers/s390/char/zcore.c +++ b/trunk/drivers/s390/char/zcore.c @@ -21,7 +21,6 @@ #include #include #include -#include "sclp.h" #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) #define MSG(x...) printk( KERN_ALERT x ) @@ -565,6 +564,8 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr) get_cpu_id(&hdr->cpu_id); } +extern int sdias_init(void); + static int __init zcore_init(void) { unsigned char arch; @@ -581,7 +582,7 @@ static int __init zcore_init(void) TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn); TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun); - rc = sclp_sdias_init(); + rc = sdias_init(); if (rc) goto fail; @@ -633,10 +634,12 @@ static int __init zcore_init(void) return rc; } +extern void sdias_exit(void); + static void __exit zcore_exit(void) { debug_unregister(zcore_dbf); - sclp_sdias_exit(); + sdias_exit(); diag308(DIAG308_REL_HSA, NULL); } diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index dfca0ef139fd..27c6d9e55b23 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -191,7 +191,8 @@ static int css_register_subchannel(struct subchannel *sch) return ret; } -static int css_probe_device(struct subchannel_id schid) +int +css_probe_device(struct subchannel_id schid) { int ret; struct subchannel *sch; diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index ed7977531c3f..71fcfdc42800 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -138,7 +138,9 @@ struct css_driver { * all css_drivers have the css_bus_type */ extern struct bus_type css_bus_type; +extern struct css_driver io_subchannel_driver; +extern int css_probe_device(struct subchannel_id); extern int css_sch_device_register(struct subchannel *); extern void css_sch_device_unregister(struct subchannel *); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index a8b373f69cf0..a23ff582db9d 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -129,7 +129,7 @@ static void io_subchannel_verify(struct device *); static void io_subchannel_ioterm(struct device *); static void io_subchannel_shutdown(struct subchannel *); -static struct css_driver io_subchannel_driver = { +struct css_driver io_subchannel_driver = { .subchannel_type = SUBCHANNEL_TYPE_IO, .drv = { .name = "io_subchannel", @@ -546,7 +546,7 @@ static struct attribute_group ccwdev_attr_group = { .attrs = ccwdev_attrs, }; -static struct attribute_group *ccwdev_attr_groups[] = { +struct attribute_group *ccwdev_attr_groups[] = { &ccwdev_attr_group, NULL, }; diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index a5d263fb55ae..16f59fcb66b1 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -616,17 +616,6 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) return chp_get_chp_desc(chpid); } -/** - * ccw_device_get_id - obtain a ccw device id - * @cdev: device to obtain the id for - * @dev_id: where to fill in the values - */ -void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id) -{ - *dev_id = cdev->private->dev_id; -} -EXPORT_SYMBOL(ccw_device_get_id); - // FIXME: these have to go: int diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index e70aeb7a3781..f770018fe1d5 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -1983,7 +1983,6 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) qdio_mark_q(q); else { - qdio_perf_stat_dec(&perf_stats.tl_runs); __qdio_inbound_processing(q); } } diff --git a/trunk/drivers/s390/net/Kconfig b/trunk/drivers/s390/net/Kconfig index eada69dec4fe..f98fa465df0a 100644 --- a/trunk/drivers/s390/net/Kconfig +++ b/trunk/drivers/s390/net/Kconfig @@ -3,7 +3,7 @@ menu "S/390 network device drivers" config LCS tristate "Lan Channel Station Interface" - depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI) + depends on NETDEVICES && (NET_ETHERNET || TR || FDDI) help Select this option if you want to use LCS networking on IBM S/390 or zSeries. This device driver supports Token Ring (IEEE 802.5), @@ -13,7 +13,7 @@ config LCS config CTC tristate "CTC device support" - depends on CCW && NETDEVICES + depends on NETDEVICES help Select this option if you want to use channel-to-channel networking on IBM S/390 or zSeries. This device driver supports real CTC @@ -42,7 +42,7 @@ config SMSGIUCV config CLAW tristate "CLAW device support" - depends on CCW && NETDEVICES + depends on NETDEVICES help This driver supports channel attached CLAW devices. CLAW is Common Link Access for Workstation. Common devices @@ -52,7 +52,7 @@ config CLAW config QETH tristate "Gigabit Ethernet device support" - depends on CCW && NETDEVICES && IP_MULTICAST && QDIO + depends on NETDEVICES && IP_MULTICAST && QDIO help This driver supports the IBM S/390 and zSeries OSA Express adapters in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 0b96d49dd636..29d176036e5c 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -2860,7 +2860,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, if (!atomic_read(&queue->set_pci_flags_count)){ /* * there's no outstanding PCI any more, so we - * have to request a PCI to be sure that the PCI + * have to request a PCI to be sure the the PCI * will wake at some time in the future then we * can flush packed buffers that might still be * hanging around, which can happen if no diff --git a/trunk/drivers/s390/net/qeth_mpc.c b/trunk/drivers/s390/net/qeth_mpc.c index f29a4bc4f6f2..f54fdfdbf06f 100644 --- a/trunk/drivers/s390/net/qeth_mpc.c +++ b/trunk/drivers/s390/net/qeth_mpc.c @@ -162,7 +162,7 @@ struct ipa_rc_msg { char *msg; }; -static struct ipa_rc_msg qeth_ipa_rc_msg[] = { +struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_SUCCESS, "success"}, {IPA_RC_NOTSUPP, "Command not supported"}, {IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"}, @@ -226,7 +226,7 @@ struct ipa_cmd_names { char *name; }; -static struct ipa_cmd_names qeth_ipa_cmd_names[] = { +struct ipa_cmd_names qeth_ipa_cmd_names[] = { {IPA_CMD_STARTLAN, "startlan"}, {IPA_CMD_STOPLAN, "stoplan"}, {IPA_CMD_SETVMAC, "setvmac"}, diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index ddff40c4212c..1f9554e08013 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/drivers/s390/scsi/zfcp_aux.c @@ -118,32 +118,97 @@ _zfcp_hex_dump(char *addr, int count) #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF -static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter) +static int zfcp_reqlist_init(struct zfcp_adapter *adapter) { - int idx; + int i; adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), GFP_KERNEL); + if (!adapter->req_list) return -ENOMEM; - for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) - INIT_LIST_HEAD(&adapter->req_list[idx]); + 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; + + /* 0 is reserved as an invalid req_id */ + if (req_id == 0) + return NULL; + + 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 idx; + unsigned int i; - for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) - if (!list_empty(&adapter->req_list[idx])) + for (i=0; ireq_list[i])) return 0; + return 1; } @@ -607,7 +672,8 @@ zfcp_sg_list_free(struct zfcp_sg_list *sg_list) * @sg_count: elements in array * Return: size of entire scatter-gather list */ -static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) +size_t +zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) { unsigned int i; struct scatterlist *p; @@ -847,8 +913,6 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) unit->sysfs_device.release = zfcp_sysfs_unit_release; dev_set_drvdata(&unit->sysfs_device, unit); - init_waitqueue_head(&unit->scsi_scan_wq); - /* mark unit unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); @@ -974,7 +1038,8 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) mempool_destroy(adapter->pool.data_gid_pn); } -static void zfcp_dummy_release(struct device *dev) +void +zfcp_dummy_release(struct device *dev) { return; } @@ -1039,7 +1104,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) /* initialize list of fsf requests */ spin_lock_init(&adapter->req_list_lock); - retval = zfcp_reqlist_alloc(adapter); + retval = zfcp_reqlist_init(adapter); if (retval) { ZFCP_LOG_INFO("request list initialization failed\n"); goto failed_low_mem_buffers; @@ -1100,7 +1165,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); sysfs_failed: dev_set_drvdata(&ccw_device->dev, NULL); - zfcp_reqlist_free(adapter); failed_low_mem_buffers: zfcp_free_low_mem_buffers(adapter); if (qdio_free(ccw_device) != 0) @@ -1334,7 +1398,7 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC -static void +void zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { @@ -1433,7 +1497,7 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) { ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port " - "with d_id 0x%06x on adapter %s\n", + "with d_id 0x%08x on adapter %s\n", status_buffer->d_id, zfcp_get_busid_by_adapter(adapter)); } else { @@ -1458,7 +1522,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter, if (!port || (port->wwpn != els_logo->nport_wwpn)) { ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port " - "with d_id 0x%06x on adapter %s\n", + "with d_id 0x%08x on adapter %s\n", status_buffer->d_id, zfcp_get_busid_by_adapter(adapter)); } else { @@ -1640,7 +1704,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) /* looks like a valid d_id */ port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); - ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%06x\n", + ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%08x\n", zfcp_get_busid_by_port(port), port->wwpn, port->d_id); goto out; diff --git a/trunk/drivers/s390/scsi/zfcp_dbf.c b/trunk/drivers/s390/scsi/zfcp_dbf.c index 5f3212440f68..d8191d115c14 100644 --- a/trunk/drivers/s390/scsi/zfcp_dbf.c +++ b/trunk/drivers/s390/scsi/zfcp_dbf.c @@ -478,7 +478,7 @@ static struct debug_view zfcp_hba_dbf_view = { NULL }; -static void +void _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id, void *buffer, int buflen) { diff --git a/trunk/drivers/s390/scsi/zfcp_def.h b/trunk/drivers/s390/scsi/zfcp_def.h index 22649639230b..32933ed54b8a 100644 --- a/trunk/drivers/s390/scsi/zfcp_def.h +++ b/trunk/drivers/s390/scsi/zfcp_def.h @@ -637,7 +637,6 @@ do { \ #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 #define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 -#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 /* FSF request status (this does not have a common part) */ #define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 @@ -981,10 +980,6 @@ struct zfcp_unit { struct scsi_device *device; /* scsi device struct pointer */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; - wait_queue_head_t scsi_scan_wq; /* can be used to wait until - all scsi_scan_target - requests have been - completed. */ }; /* FSF request */ @@ -1089,42 +1084,6 @@ extern void _zfcp_hex_dump(char *, int); #define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter)) #define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port)) -/* - * Helper functions for request ID management. - */ -static inline int zfcp_reqlist_hash(unsigned long req_id) -{ - return req_id % REQUEST_LIST_SIZE; -} - -static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter, - struct zfcp_fsf_req *fsf_req) -{ - unsigned int idx; - - idx = zfcp_reqlist_hash(fsf_req->req_id); - list_add_tail(&fsf_req->list, &adapter->req_list[idx]); -} - -static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter, - struct zfcp_fsf_req *fsf_req) -{ - list_del(&fsf_req->list); -} - -static inline struct zfcp_fsf_req * -zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id) -{ - struct zfcp_fsf_req *request; - unsigned int idx; - - idx = zfcp_reqlist_hash(req_id); - list_for_each_entry(request, &adapter->req_list[idx], list) - if (request->req_id == req_id) - return request; - return NULL; -} - /* * functions needed for reference/usage counting */ diff --git a/trunk/drivers/s390/scsi/zfcp_erp.c b/trunk/drivers/s390/scsi/zfcp_erp.c index aef66bc2b6ca..c1f2d4b14c2b 100644 --- a/trunk/drivers/s390/scsi/zfcp_erp.c +++ b/trunk/drivers/s390/scsi/zfcp_erp.c @@ -179,7 +179,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter) static void zfcp_fsf_request_timeout_handler(unsigned long data) { struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; - zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); + zfcp_erp_adapter_reopen(adapter, 0); } void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) @@ -342,9 +342,9 @@ zfcp_erp_adisc(struct zfcp_port *port) adisc->wwpn = fc_host_port_name(adapter->scsi_host); adisc->wwnn = fc_host_node_name(adapter->scsi_host); adisc->nport_id = fc_host_port_id(adapter->scsi_host); - ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x " + ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " "(wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%06x, nport_id=0x%06x)\n", + "hard_nport_id=0x%08x, nport_id=0x%08x)\n", adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, adisc->hard_nport_id, adisc->nport_id); @@ -352,7 +352,7 @@ zfcp_erp_adisc(struct zfcp_port *port) retval = zfcp_fsf_send_els(send_els); if (retval != 0) { ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " - "0x%06x on adapter %s\n", send_els->d_id, + "0x%08x on adapter %s\n", send_els->d_id, zfcp_get_busid_by_adapter(adapter)); goto freemem; } @@ -398,7 +398,7 @@ zfcp_erp_adisc_handler(unsigned long data) if (send_els->status != 0) { ZFCP_LOG_NORMAL("ELS request rejected/timed out, " "force physical port reopen " - "(adapter %s, port d_id=0x%06x)\n", + "(adapter %s, port d_id=0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); debug_text_event(adapter->erp_dbf, 3, "forcreop"); if (zfcp_erp_port_forced_reopen(port, 0)) @@ -411,9 +411,9 @@ zfcp_erp_adisc_handler(unsigned long data) adisc = zfcp_sg_to_address(send_els->resp); - ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id " - "0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%06x, nport_id=0x%06x)\n", + ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "hard_nport_id=0x%08x, nport_id=0x%08x)\n", d_id, fc_host_port_id(adapter->scsi_host), (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, adisc->hard_nport_id, adisc->nport_id); @@ -847,7 +847,8 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) if (erp_action->fsf_req) { /* take lock to ensure that request is not deleted meanwhile */ spin_lock(&adapter->req_list_lock); - if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) { + if (zfcp_reqlist_ismember(adapter, + erp_action->fsf_req->req_id)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, @@ -1376,7 +1377,7 @@ zfcp_erp_port_failed(struct zfcp_port *port) if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) ZFCP_LOG_NORMAL("port erp failed (adapter %s, " - "port d_id=0x%06x)\n", + "port d_id=0x%08x)\n", zfcp_get_busid_by_port(port), port->d_id); else ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n", @@ -1590,62 +1591,6 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) return result; } -struct zfcp_erp_add_work { - struct zfcp_unit *unit; - struct work_struct work; -}; - -/** - * zfcp_erp_scsi_scan - * @data: pointer to a struct zfcp_erp_add_work - * - * Registers a logical unit with the SCSI stack. - */ -static void zfcp_erp_scsi_scan(struct work_struct *work) -{ - struct zfcp_erp_add_work *p = - container_of(work, struct zfcp_erp_add_work, work); - struct zfcp_unit *unit = p->unit; - struct fc_rport *rport = unit->port->rport; - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, - unit->scsi_lun, 0); - atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); - wake_up(&unit->scsi_scan_wq); - zfcp_unit_put(unit); - kfree(p); -} - -/** - * zfcp_erp_schedule_work - * @unit: pointer to unit which should be registered with SCSI stack - * - * Schedules work which registers a unit with the SCSI stack - */ -static void -zfcp_erp_schedule_work(struct zfcp_unit *unit) -{ - struct zfcp_erp_add_work *p; - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) { - ZFCP_LOG_NORMAL("error: Out of resources. Could not register " - "the FCP-LUN 0x%Lx connected to " - "the port with WWPN 0x%Lx connected to " - "the adapter %s with the SCSI stack.\n", - unit->fcp_lun, - unit->port->wwpn, - zfcp_get_busid_by_unit(unit)); - return; - } - - zfcp_unit_get(unit); - memset(p, 0, sizeof(*p)); - atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); - INIT_WORK(&p->work, zfcp_erp_scsi_scan); - p->unit = unit; - schedule_work(&p->work); -} - /* * function: * @@ -2456,7 +2401,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) retval = ZFCP_ERP_FAILED; } } else { - ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> " + ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> " "trying open\n", port->wwpn, port->d_id); retval = zfcp_erp_port_strategy_open_port(erp_action); } @@ -2496,7 +2441,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) case ZFCP_ERP_STEP_UNINITIALIZED: case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: - ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n", + ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> trying open\n", port->wwpn, port->d_id); retval = zfcp_erp_port_strategy_open_port(erp_action); break; @@ -3147,9 +3092,9 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, && port->rport) { atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); - if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, - &unit->status) == 0) - zfcp_erp_schedule_work(unit); + scsi_scan_target(&port->rport->dev, 0, + port->rport->scsi_target_id, + unit->scsi_lun, 0); } zfcp_unit_put(unit); break; @@ -3176,7 +3121,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, zfcp_get_busid_by_port(port), port->wwpn); else { - scsi_target_unblock(&port->rport->dev); + scsi_flush_work(adapter->scsi_host); port->rport->maxframe_size = port->maxframe_size; port->rport->supported_classes = port->supported_classes; diff --git a/trunk/drivers/s390/scsi/zfcp_ext.h b/trunk/drivers/s390/scsi/zfcp_ext.h index 991d45667a44..01386ac688a2 100644 --- a/trunk/drivers/s390/scsi/zfcp_ext.h +++ b/trunk/drivers/s390/scsi/zfcp_ext.h @@ -184,6 +184,10 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, unsigned long); 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 a8b02542ac2d..4c0a59afd5c8 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.c +++ b/trunk/drivers/s390/scsi/zfcp_fsf.c @@ -828,7 +828,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) { ZFCP_LOG_NORMAL("bug: Reopen port indication received for" - "nonexisting port with d_id 0x%06x on " + "nonexisting port with d_id 0x%08x on " "adapter %s. Ignored.\n", status_buffer->d_id & ZFCP_DID_MASK, zfcp_get_busid_by_adapter(adapter)); @@ -853,7 +853,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) &status_buffer->status_subtype, sizeof (u32)); ZFCP_LOG_NORMAL("bug: Undefined status subtype received " "for a reopen indication on port with " - "d_id 0x%06x on the adapter %s. " + "d_id 0x%08x on the adapter %s. " "Ignored. (debug info 0x%x)\n", status_buffer->d_id, zfcp_get_busid_by_adapter(adapter), @@ -1156,7 +1156,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id, } ZFCP_LOG_DEBUG("Abort FCP Command request initiated " - "(adapter%s, port d_id=0x%06x, " + "(adapter%s, port d_id=0x%08x, " "unit x%016Lx, old_req_id=0x%lx)\n", zfcp_get_busid_by_adapter(adapter), unit->port->d_id, @@ -1554,7 +1554,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) case FSF_ACCESS_DENIED: ZFCP_LOG_NORMAL("access denied, cannot send generic service " - "command (adapter %s, port d_id=0x%06x)\n", + "command (adapter %s, port d_id=0x%08x)\n", zfcp_get_busid_by_port(port), port->d_id); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; @@ -1576,7 +1576,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) case FSF_GENERIC_COMMAND_REJECTED: ZFCP_LOG_INFO("generic service command rejected " - "(adapter %s, port d_id=0x%06x)\n", + "(adapter %s, port d_id=0x%08x)\n", zfcp_get_busid_by_port(port), port->d_id); ZFCP_LOG_INFO("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, @@ -1602,7 +1602,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) case FSF_PORT_BOXED: ZFCP_LOG_INFO("port needs to be reopened " - "(adapter %s, port d_id=0x%06x)\n", + "(adapter %s, port d_id=0x%08x)\n", zfcp_get_busid_by_port(port), port->d_id); debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); zfcp_erp_port_boxed(port); @@ -1683,7 +1683,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) NULL, &lock_flags, &fsf_req); if (ret < 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " - "(adapter %s, port d_id: 0x%06x)\n", + "(adapter %s, port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto failed_req; } @@ -1708,7 +1708,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) ZFCP_MAX_SBALS_PER_ELS_REQ); if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " - "(adapter %s, port d_id: 0x%06x)\n", + "(adapter %s, port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); if (bytes == 0) { ret = -ENOMEM; @@ -1725,7 +1725,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) ZFCP_MAX_SBALS_PER_ELS_REQ); if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " - "(adapter %s, port d_id: 0x%06x)\n", + "(adapter %s, port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); if (bytes == 0) { ret = -ENOMEM; @@ -1739,7 +1739,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) /* reject request */ ZFCP_LOG_INFO("error: microcode does not support chained SBALs" ", ELS request too big (adapter %s, " - "port d_id: 0x%06x)\n", + "port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); ret = -EOPNOTSUPP; goto failed_send; @@ -1760,13 +1760,13 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) ret = zfcp_fsf_req_send(fsf_req); if (ret) { ZFCP_LOG_DEBUG("error: initiation of ELS request failed " - "(adapter %s, port d_id: 0x%06x)\n", + "(adapter %s, port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto failed_send; } ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: " - "0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); + "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto out; failed_send: @@ -1859,7 +1859,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) case FSF_ELS_COMMAND_REJECTED: ZFCP_LOG_INFO("ELS has been rejected because command filter " "prohibited sending " - "(adapter: %s, port d_id: 0x%06x)\n", + "(adapter: %s, port d_id: 0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); break; @@ -1907,7 +1907,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) case FSF_ACCESS_DENIED: ZFCP_LOG_NORMAL("access denied, cannot send ELS command " - "(adapter %s, port d_id=0x%06x)\n", + "(adapter %s, port d_id=0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; @@ -2070,7 +2070,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" "WWNN 0x%016Lx, " "WWPN 0x%016Lx, " - "S_ID 0x%06x,\n" + "S_ID 0x%08x,\n" "adapter version 0x%x, " "LIC version 0x%x, " "FC link speed %d Gb/s\n", @@ -3043,7 +3043,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) queue_designator = &header->fsf_status_qual.fsf_queue_designator; atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_COMMON_ACCESS_BOXED | ZFCP_STATUS_UNIT_SHARED | ZFCP_STATUS_UNIT_READONLY, &unit->status); @@ -4646,22 +4645,23 @@ 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); + + /* this is serialized (we are holding req_queue-lock of adapter */ + if (adapter->req_no == 0) + adapter->req_no++; + fsf_req->req_id = adapter->req_no++; + init_timer(&fsf_req->timer); + zfcp_fsf_req_qtcb_init(fsf_req); /* initialize waitqueue which may be used to wait on this request completion */ init_waitqueue_head(&fsf_req->completion_wq); ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags); - if (ret < 0) + if(ret < 0) { goto failed_sbals; - - /* this is serialized (we are holding req_queue-lock of adapter) */ - if (adapter->req_no == 0) - adapter->req_no++; - fsf_req->req_id = adapter->req_no++; - - zfcp_fsf_req_qtcb_init(fsf_req); + } /* * We hold queue_lock here. Check if QDIOUP is set and let request fail @@ -4788,7 +4788,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req) retval = -EIO; del_timer(&fsf_req->timer); spin_lock(&adapter->req_list_lock); - zfcp_reqlist_remove(adapter, fsf_req); + zfcp_reqlist_remove(adapter, fsf_req->req_id); spin_unlock(&adapter->req_list_lock); /* undo changes in request queue made for this request */ zfcp_qdio_zero_sbals(req_queue->buffer, diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index bdf5782b8a7a..1e12a78e8edd 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -222,7 +222,7 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, * Since we have been using this adapter, it is save to assume * that it is not failed but recoverable. The card seems to * report link-up events by self-initiated queue shutdown. - * That is why we need to clear the link-down flag + * That is why we need to clear the the link-down flag * which is set again in case we have missed by a mile. */ zfcp_erp_adapter_reopen( @@ -283,10 +283,10 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, } /** - * zfcp_qdio_reqid_check - checks for valid reqids. + * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status */ -static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, - unsigned long req_id) +static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, + unsigned long req_id) { struct zfcp_fsf_req *fsf_req; unsigned long flags; @@ -294,22 +294,23 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, debug_long_event(adapter->erp_dbf, 4, req_id); spin_lock_irqsave(&adapter->req_list_lock, flags); - fsf_req = zfcp_reqlist_find(adapter, req_id); + fsf_req = zfcp_reqlist_ismember(adapter, req_id); - if (!fsf_req) - /* - * Unknown request means that we have potentially memory - * corruption and must stop the machine immediatly. - */ - panic("error: unknown request id (%ld) on adapter %s.\n", - req_id, zfcp_get_busid_by_adapter(adapter)); + 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, fsf_req); + 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; } /* @@ -373,9 +374,27 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, /* look for QDIO request identifiers in SB */ buffere = &buffer->element[buffere_index]; - zfcp_qdio_reqid_check(adapter, - (unsigned long) buffere->addr); - + retval = zfcp_qdio_reqid_check(adapter, + (unsigned long) buffere->addr); + + if (retval) { + ZFCP_LOG_NORMAL("bug: unexpected inbound " + "packet on adapter %s " + "(reqid=0x%lx, " + "first_element=%d, " + "elements_processed=%d)\n", + zfcp_get_busid_by_adapter(adapter), + (unsigned long) buffere->addr, + first_element, + elements_processed); + ZFCP_LOG_NORMAL("hex dump of inbound buffer " + "at address %p " + "(buffer_index=%d, " + "buffere_index=%d)\n", buffer, + buffer_index, buffere_index); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, + (char *) buffer, SBAL_SIZE); + } /* * A single used SBALE per inbound SBALE has been * implemented by QDIO so far. Hope they will diff --git a/trunk/drivers/s390/scsi/zfcp_scsi.c b/trunk/drivers/s390/scsi/zfcp_scsi.c index 16e2d64658af..99db02062c3b 100644 --- a/trunk/drivers/s390/scsi/zfcp_scsi.c +++ b/trunk/drivers/s390/scsi/zfcp_scsi.c @@ -22,7 +22,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI #include "zfcp_ext.h" -#include static void zfcp_scsi_slave_destroy(struct scsi_device *sdp); static int zfcp_scsi_slave_alloc(struct scsi_device *sdp); @@ -180,10 +179,6 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; if (unit) { - zfcp_erp_wait(unit->port->adapter); - wait_event(unit->scsi_scan_wq, - atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, - &unit->status) == 0); atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); sdpnt->hostdata = NULL; unit->device = NULL; @@ -407,8 +402,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) /* Check whether corresponding fsf_req is still pending */ spin_lock(&adapter->req_list_lock); - fsf_req = zfcp_reqlist_find(adapter, - (unsigned long) scpnt->host_scribble); + fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long) + scpnt->host_scribble); spin_unlock(&adapter->req_list_lock); if (!fsf_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); diff --git a/trunk/drivers/sbus/char/bpp.c b/trunk/drivers/sbus/char/bpp.c index 4fab0c23814c..74b999d77bbf 100644 --- a/trunk/drivers/sbus/char/bpp.c +++ b/trunk/drivers/sbus/char/bpp.c @@ -156,7 +156,7 @@ static unsigned short get_pins(unsigned minor) #define BPP_ICR 0x18 #define BPP_SIZE 0x1A -/* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */ +/* BPP_CSR. Bits of type RW1 are cleared with writting '1'. */ #define P_DEV_ID_MASK 0xf0000000 /* R */ #define P_DEV_ID_ZEBRA 0x40000000 #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ diff --git a/trunk/drivers/scsi/aacraid/comminit.c b/trunk/drivers/scsi/aacraid/comminit.c index 3009ad8c4073..33682ce96a5d 100644 --- a/trunk/drivers/scsi/aacraid/comminit.c +++ b/trunk/drivers/scsi/aacraid/comminit.c @@ -387,11 +387,12 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) * Ok now init the communication subsystem */ - dev->queues = kzalloc(sizeof(struct aac_queue_block), GFP_KERNEL); + dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); if (dev->queues == NULL) { printk(KERN_ERR "Error could not allocate comm region.\n"); return NULL; } + memset(dev->queues, 0, sizeof(struct aac_queue_block)); if (aac_comm_init(dev)<0){ kfree(dev->queues); diff --git a/trunk/drivers/scsi/aacraid/commsup.c b/trunk/drivers/scsi/aacraid/commsup.c index 9aca57eda943..5824a757a753 100644 --- a/trunk/drivers/scsi/aacraid/commsup.c +++ b/trunk/drivers/scsi/aacraid/commsup.c @@ -1223,11 +1223,13 @@ int aac_check_health(struct aac_dev * aac) * Warning: no sleep allowed while * holding spinlock */ - hw_fib = kzalloc(sizeof(struct hw_fib), GFP_ATOMIC); - fib = kzalloc(sizeof(struct fib), GFP_ATOMIC); + hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); + fib = kmalloc(sizeof(struct fib), GFP_ATOMIC); if (fib && hw_fib) { struct aac_aifcmd * aif; + memset(hw_fib, 0, sizeof(struct hw_fib)); + memset(fib, 0, sizeof(struct fib)); fib->hw_fib_va = hw_fib; fib->dev = aac; aac_fib_init(fib); diff --git a/trunk/drivers/scsi/aacraid/dpcsup.c b/trunk/drivers/scsi/aacraid/dpcsup.c index fcd25f7d0bc6..42c7dcda6d9b 100644 --- a/trunk/drivers/scsi/aacraid/dpcsup.c +++ b/trunk/drivers/scsi/aacraid/dpcsup.c @@ -248,14 +248,16 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) * manage the linked lists. */ if ((!dev->aif_thread) - || (!(fib = kzalloc(sizeof(struct fib),GFP_ATOMIC)))) + || (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC)))) return 1; - if (!(hw_fib = kzalloc(sizeof(struct hw_fib),GFP_ATOMIC))) { + if (!(hw_fib = kmalloc(sizeof(struct hw_fib),GFP_ATOMIC))) { kfree (fib); return 1; } + memset(hw_fib, 0, sizeof(struct hw_fib)); memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib)); + memset(fib, 0, sizeof(struct fib)); INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof(struct fib); diff --git a/trunk/drivers/scsi/aacraid/rx.c b/trunk/drivers/scsi/aacraid/rx.c index 291cd14f4e98..0c71315cbf1a 100644 --- a/trunk/drivers/scsi/aacraid/rx.c +++ b/trunk/drivers/scsi/aacraid/rx.c @@ -539,10 +539,8 @@ int _aac_rx_init(struct aac_dev *dev) } /* Failure to reset here is an option ... */ - dev->a_ops.adapter_sync_cmd = rx_sync_cmd; - dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt; dev->OIMR = status = rx_readb (dev, MUnit.OIMR); - if ((((status & 0x0c) != 0x0c) || reset_devices) && + if ((((status & 0xff) != 0xff) || reset_devices) && !aac_rx_restart_adapter(dev, 0)) ++restart; /* diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada0028aa0..8d72bbae96ad 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -966,7 +966,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd) | AHD_BUSFREEREV_BUG; ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; - /* If the user requested that the SLOWCRC bit to be set. */ + /* If the user requested the the SLOWCRC bit to be set. */ if (aic79xx_slowcrc) ahd->features |= AHD_AIC79XXB_SLOWCRC; diff --git a/trunk/drivers/scsi/aic94xx/Makefile b/trunk/drivers/scsi/aic94xx/Makefile index e78ce0fa44d2..e6b70123940c 100644 --- a/trunk/drivers/scsi/aic94xx/Makefile +++ b/trunk/drivers/scsi/aic94xx/Makefile @@ -6,7 +6,7 @@ # # This file is licensed under GPLv2. # -# This file is part of the aic94xx driver. +# This file is part of the the aic94xx driver. # # The aic94xx driver is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as diff --git a/trunk/drivers/scsi/ch.c b/trunk/drivers/scsi/ch.c index 2311019304c0..2a2cc6cf1182 100644 --- a/trunk/drivers/scsi/ch.c +++ b/trunk/drivers/scsi/ch.c @@ -319,9 +319,10 @@ ch_readconfig(scsi_changer *ch) int result,id,lun,i; u_int elem; - buffer = kzalloc(512, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) return -ENOMEM; + memset(buffer,0,512); memset(cmd,0,sizeof(cmd)); cmd[0] = MODE_SENSE; @@ -529,9 +530,10 @@ ch_set_voltag(scsi_changer *ch, u_int elem, u_char *buffer; int result; - buffer = kzalloc(512, GFP_KERNEL); + buffer = kmalloc(512, GFP_KERNEL); if (!buffer) return -ENOMEM; + memset(buffer,0,512); dprintk("%s %s voltag: 0x%x => \"%s\"\n", clear ? "clear" : "set", @@ -920,10 +922,11 @@ static int ch_probe(struct device *dev) if (sd->type != TYPE_MEDIUM_CHANGER) return -ENODEV; - ch = kzalloc(sizeof(*ch), GFP_KERNEL); + ch = kmalloc(sizeof(*ch), GFP_KERNEL); if (NULL == ch) return -ENOMEM; + memset(ch,0,sizeof(*ch)); ch->minor = ch_devcount; sprintf(ch->name,"ch%d",ch->minor); mutex_init(&ch->lock); diff --git a/trunk/drivers/scsi/dc395x.c b/trunk/drivers/scsi/dc395x.c index 564ea90ed3a0..a965ed3548d5 100644 --- a/trunk/drivers/scsi/dc395x.c +++ b/trunk/drivers/scsi/dc395x.c @@ -541,7 +541,7 @@ static struct ParameterData __devinitdata cfg_data[] = { /* - * Safe settings. If set to zero the BIOS/default values with + * Safe settings. If set to zero the the BIOS/default values with * command line overrides will be used. If set to 1 then safe and * slow settings will be used. */ @@ -617,7 +617,7 @@ static void __devinit fix_settings(void) /* * Mapping from the eeprom delay index value (index into this array) - * to the number of actual seconds that the delay should be for. + * to the the number of actual seconds that the delay should be for. */ static char __devinitdata eeprom_index_to_delay_map[] = { 1, 3, 5, 10, 16, 30, 60, 120 }; @@ -4136,7 +4136,7 @@ static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long * @io_port: base I/O address * @addr: offset into SEEPROM * - * Returns the byte read. + * Returns the the byte read. **/ static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr) { diff --git a/trunk/drivers/scsi/dpt_i2o.c b/trunk/drivers/scsi/dpt_i2o.c index 8c7d2bbf9b1a..fb6433a56989 100644 --- a/trunk/drivers/scsi/dpt_i2o.c +++ b/trunk/drivers/scsi/dpt_i2o.c @@ -1308,12 +1308,13 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); - status = kzalloc(4, GFP_KERNEL|ADDR32); + status = kmalloc(4, GFP_KERNEL|ADDR32); if(status == NULL) { adpt_send_nop(pHba, m); printk(KERN_ERR"IOP reset failed - no free memory.\n"); return -ENOMEM; } + memset(status,0,4); msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; @@ -1503,19 +1504,21 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) continue; } if( pHba->channel[bus_no].device[scsi_id] == NULL){ - pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); if(pDev == NULL) { return -ENOMEM; } pHba->channel[bus_no].device[scsi_id] = pDev; + memset(pDev,0,sizeof(struct adpt_device)); } else { for( pDev = pHba->channel[bus_no].device[scsi_id]; pDev->next_lun; pDev = pDev->next_lun){ } - pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); if(pDev->next_lun == NULL) { return -ENOMEM; } + memset(pDev->next_lun,0,sizeof(struct adpt_device)); pDev = pDev->next_lun; } pDev->tid = tid; @@ -1664,11 +1667,12 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) reply_size = REPLY_FRAME_SIZE; } reply_size *= 4; - reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); + reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); if(reply == NULL) { printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name); return -ENOMEM; } + memset(reply,0,REPLY_FRAME_SIZE*4); sg_offset = (msg[0]>>4)&0xf; msg[2] = 0x40000000; // IOCTL context msg[3] = (u32)reply; @@ -2440,7 +2444,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) } pDev = pHba->channel[bus_no].device[scsi_id]; if( pDev == NULL){ - pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); if(pDev == NULL) { return -ENOMEM; } @@ -2449,11 +2453,12 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) while (pDev->next_lun) { pDev = pDev->next_lun; } - pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL); if(pDev == NULL) { return -ENOMEM; } } + memset(pDev,0,sizeof(struct adpt_device)); pDev->tid = d->lct_data.tid; pDev->scsi_channel = bus_no; pDev->scsi_id = scsi_id; diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index 8263f752809d..2b5b8a93bc10 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -721,23 +721,19 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r return ide_stopped; } -#ifdef CONFIG_IDE_PROC_FS static void idescsi_add_settings(ide_drive_t *drive) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); - ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "transform", SETTING_RW, -1, -1, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); + ide_add_setting(drive, "log", SETTING_RW, -1, -1, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); } -#else -static inline void idescsi_add_settings(ide_drive_t *drive) { ; } -#endif /* * Driver initialization. @@ -760,7 +756,7 @@ static void ide_scsi_remove(ide_drive_t *drive) struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; - ide_proc_unregister_driver(drive, scsi->driver); + ide_unregister_subdriver(drive, scsi->driver); ide_unregister_region(g); @@ -774,11 +770,13 @@ static void ide_scsi_remove(ide_drive_t *drive) static int ide_scsi_probe(ide_drive_t *); -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static ide_proc_entry_t idescsi_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; +#else +# define idescsi_proc NULL #endif static ide_driver_t idescsi_driver = { @@ -792,13 +790,11 @@ static ide_driver_t idescsi_driver = { .version = IDESCSI_VERSION, .media = ide_scsi, .supports_dsc_overlap = 0, + .proc = idescsi_proc, .do_request = idescsi_do_request, .end_request = idescsi_end_request, .error = idescsi_atapi_error, .abort = idescsi_atapi_abort, -#ifdef CONFIG_IDE_PROC_FS - .proc = idescsi_proc, -#endif }; static int idescsi_ide_open(struct inode *inode, struct file *filp) @@ -1157,7 +1153,7 @@ static int ide_scsi_probe(ide_drive_t *drive) idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; - ide_proc_register_driver(drive, &idescsi_driver); + ide_register_subdriver(drive, &idescsi_driver); err = 0; idescsi_setup(drive, idescsi); g->fops = &idescsi_ops; @@ -1169,7 +1165,7 @@ static int ide_scsi_probe(ide_drive_t *drive) } /* fall through on error */ ide_unregister_region(g); - ide_proc_unregister_driver(drive, &idescsi_driver); + ide_unregister_subdriver(drive, &idescsi_driver); put_disk(g); out_host_put: diff --git a/trunk/drivers/scsi/ipr.c b/trunk/drivers/scsi/ipr.c index 4baa79e68679..2c7b77e833f9 100644 --- a/trunk/drivers/scsi/ipr.c +++ b/trunk/drivers/scsi/ipr.c @@ -92,7 +92,6 @@ static unsigned int ipr_fastfail = 0; static unsigned int ipr_transop_timeout = 0; static unsigned int ipr_enable_cache = 1; static unsigned int ipr_debug = 0; -static unsigned int ipr_dual_ioa_raid = 1; static DEFINE_SPINLOCK(ipr_driver_lock); /* This table describes the differences between DMA controller chips */ @@ -159,8 +158,6 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0); MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); module_param_named(debug, ipr_debug, int, 0); MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); -module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0); -MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)"); MODULE_LICENSE("GPL"); MODULE_VERSION(IPR_DRIVER_VERSION); @@ -209,8 +206,6 @@ struct ipr_error_table_t ipr_error_table[] = { "8009: Impending cache battery pack failure"}, {0x02040400, 0, 0, "34FF: Disk device format in progress"}, - {0x02048000, 0, IPR_DEFAULT_LOG_LEVEL, - "9070: IOA requested reset"}, {0x023F0000, 0, 0, "Synchronization required"}, {0x024E0000, 0, 0, @@ -955,53 +950,6 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) } } -/** - * strip_and_pad_whitespace - Strip and pad trailing whitespace. - * @i: index into buffer - * @buf: string to modify - * - * This function will strip all trailing whitespace, pad the end - * of the string with a single space, and NULL terminate the string. - * - * Return value: - * new length of string - **/ -static int strip_and_pad_whitespace(int i, char *buf) -{ - while (i && buf[i] == ' ') - i--; - buf[i+1] = ' '; - buf[i+2] = '\0'; - return i + 2; -} - -/** - * ipr_log_vpd_compact - Log the passed extended VPD compactly. - * @prefix: string to print at start of printk - * @hostrcb: hostrcb pointer - * @vpd: vendor/product id/sn struct - * - * Return value: - * none - **/ -static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb, - struct ipr_vpd *vpd) -{ - char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3]; - int i = 0; - - memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN); - i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer); - - memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN); - i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer); - - memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN); - buffer[IPR_SERIAL_NUM_LEN + i] = '\0'; - - ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer); -} - /** * ipr_log_vpd - Log the passed VPD to the error log. * @vpd: vendor/product id/sn struct @@ -1025,23 +973,6 @@ static void ipr_log_vpd(struct ipr_vpd *vpd) ipr_err(" Serial Number: %s\n", buffer); } -/** - * ipr_log_ext_vpd_compact - Log the passed extended VPD compactly. - * @prefix: string to print at start of printk - * @hostrcb: hostrcb pointer - * @vpd: vendor/product id/sn/wwn struct - * - * Return value: - * none - **/ -static void ipr_log_ext_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb, - struct ipr_ext_vpd *vpd) -{ - ipr_log_vpd_compact(prefix, hostrcb, &vpd->vpd); - ipr_hcam_err(hostrcb, "%s WWN: %08X%08X\n", prefix, - be32_to_cpu(vpd->wwid[0]), be32_to_cpu(vpd->wwid[1])); -} - /** * ipr_log_ext_vpd - Log the passed extended VPD to the error log. * @vpd: vendor/product id/sn/wwn struct @@ -1356,11 +1287,10 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, error = &hostrcb->hcam.u.error.u.type_17_error; error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; - strstrip(error->failure_reason); - ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, - be32_to_cpu(hostrcb->hcam.u.error.prc)); - ipr_log_ext_vpd_compact("Remote IOA", hostrcb, &error->vpd); + ipr_err("%s\n", error->failure_reason); + ipr_err("Remote Adapter VPD:\n"); + ipr_log_ext_vpd(&error->vpd); ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + @@ -1382,11 +1312,10 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, error = &hostrcb->hcam.u.error.u.type_07_error; error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; - strstrip(error->failure_reason); - ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, - be32_to_cpu(hostrcb->hcam.u.error.prc)); - ipr_log_vpd_compact("Remote IOA", hostrcb, &error->vpd); + ipr_err("%s\n", error->failure_reason); + ipr_err("Remote Adapter VPD:\n"); + ipr_log_vpd(&error->vpd); ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + @@ -1743,15 +1672,12 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); - u32 fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); list_del(&hostrcb->queue); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); if (!ioasc) { ipr_handle_log_data(ioa_cfg, hostrcb); - if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) - ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); } else if (ioasc != IPR_IOASC_IOA_WAS_RESET) { dev_err(&ioa_cfg->pdev->dev, "Host RCB failed with IOASC: 0x%08X\n", ioasc); @@ -2709,13 +2635,8 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev, if (!capable(CAP_SYS_ADMIN)) return -EACCES; + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while(ioa_cfg->in_reset_reload) { - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); - spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - } - ioa_cfg->errors_logged = 0; ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NORMAL); @@ -3037,11 +2958,6 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg, unsigned long lock_flags; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while(ioa_cfg->in_reset_reload) { - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); - spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - } if (ioa_cfg->ucode_sglist) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); @@ -4740,19 +4656,18 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; struct ipr_resource_entry *res = scsi_cmd->device->hostdata; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); - u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK; if (!res) { ipr_scsi_eh_done(ipr_cmd); return; } - if (!ipr_is_gscsi(res) && masked_ioasc != IPR_IOASC_HW_DEV_BUS_STATUS) + if (!ipr_is_gscsi(res)) ipr_gen_sense(ipr_cmd); ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); - switch (masked_ioasc) { + switch (ioasc & IPR_IOASC_IOASC_MASK) { case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST: if (ipr_is_naca_model(res)) scsi_cmd->result |= (DID_ABORT << 16); @@ -5448,7 +5363,6 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd) ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb); } - scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS); dev_info(&ioa_cfg->pdev->dev, "IOA initialized.\n"); ioa_cfg->reset_retries = 0; @@ -5884,94 +5798,6 @@ static int ipr_ioafp_mode_sense_page28(struct ipr_cmnd *ipr_cmd) return IPR_RC_JOB_RETURN; } -/** - * ipr_ioafp_mode_select_page24 - Issue Mode Select to IOA - * @ipr_cmd: ipr command struct - * - * This function enables dual IOA RAID support if possible. - * - * Return value: - * IPR_RC_JOB_RETURN - **/ -static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - struct ipr_mode_pages *mode_pages = &ioa_cfg->vpd_cbs->mode_pages; - struct ipr_mode_page24 *mode_page; - int length; - - ENTER; - mode_page = ipr_get_mode_page(mode_pages, 0x24, - sizeof(struct ipr_mode_page24)); - - if (mode_page) - mode_page->flags |= IPR_ENABLE_DUAL_IOA_AF; - - length = mode_pages->hdr.length + 1; - mode_pages->hdr.length = 0; - - ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11, - ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages), - length); - - ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; - ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); - - LEAVE; - return IPR_RC_JOB_RETURN; -} - -/** - * ipr_reset_mode_sense_page24_failed - Handle failure of IOAFP mode sense - * @ipr_cmd: ipr command struct - * - * This function handles the failure of a Mode Sense to the IOAFP. - * Some adapters do not handle all mode pages. - * - * Return value: - * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN - **/ -static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) -{ - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); - - if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { - ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; - return IPR_RC_JOB_CONTINUE; - } - - return ipr_reset_cmd_failed(ipr_cmd); -} - -/** - * ipr_ioafp_mode_sense_page24 - Issue Page 24 Mode Sense to IOA - * @ipr_cmd: ipr command struct - * - * This function send a mode sense to the IOA to retrieve - * the IOA Advanced Function Control mode page. - * - * Return value: - * IPR_RC_JOB_RETURN - **/ -static int ipr_ioafp_mode_sense_page24(struct ipr_cmnd *ipr_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - - ENTER; - ipr_build_mode_sense(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), - 0x24, ioa_cfg->vpd_cbs_dma + - offsetof(struct ipr_misc_cbs, mode_pages), - sizeof(struct ipr_mode_pages)); - - ipr_cmd->job_step = ipr_ioafp_mode_select_page24; - ipr_cmd->job_step_failed = ipr_reset_mode_sense_page24_failed; - - ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); - - LEAVE; - return IPR_RC_JOB_RETURN; -} - /** * ipr_init_res_table - Initialize the resource table * @ipr_cmd: ipr command struct @@ -6040,10 +5866,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) } } - if (ioa_cfg->dual_raid && ipr_dual_ioa_raid) - ipr_cmd->job_step = ipr_ioafp_mode_sense_page24; - else - ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; + ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; LEAVE; return IPR_RC_JOB_CONTINUE; @@ -6065,11 +5888,8 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data; - struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; ENTER; - if (cap->cap & IPR_CAP_DUAL_IOA_RAID) - ioa_cfg->dual_raid = 1; dev_info(&ioa_cfg->pdev->dev, "Adapter firmware version: %02X%02X%02X%02X\n", ucode_vpd->major_release, ucode_vpd->card_type, ucode_vpd->minor_release[0], ucode_vpd->minor_release[1]); @@ -6152,37 +5972,6 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page) return 0; } -/** - * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. - * @ipr_cmd: ipr command struct - * - * This function sends a Page 0xD0 inquiry to the adapter - * to retrieve adapter capabilities. - * - * Return value: - * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN - **/ -static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data; - struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; - - ENTER; - ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; - memset(cap, 0, sizeof(*cap)); - - if (ipr_inquiry_page_supported(page0, 0xD0)) { - ipr_ioafp_inquiry(ipr_cmd, 1, 0xD0, - ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, cap), - sizeof(struct ipr_inquiry_cap)); - return IPR_RC_JOB_RETURN; - } - - LEAVE; - return IPR_RC_JOB_CONTINUE; -} - /** * ipr_ioafp_page3_inquiry - Send a Page 3 Inquiry to the adapter. * @ipr_cmd: ipr command struct @@ -6203,7 +5992,7 @@ static int ipr_ioafp_page3_inquiry(struct ipr_cmnd *ipr_cmd) if (!ipr_inquiry_page_supported(page0, 1)) ioa_cfg->cache_state = CACHE_NONE; - ipr_cmd->job_step = ipr_ioafp_cap_inquiry; + ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; ipr_ioafp_inquiry(ipr_cmd, 1, 3, ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, page3_data), @@ -6489,7 +6278,6 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) struct ipr_hostrcb *hostrcb; struct ipr_uc_sdt sdt; int rc, length; - u32 ioasc; mailbox = readl(ioa_cfg->ioa_mailbox); @@ -6522,13 +6310,9 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) (__be32 *)&hostrcb->hcam, min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32)); - if (!rc) { + if (!rc) ipr_handle_log_data(ioa_cfg, hostrcb); - ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); - if (ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED && - ioa_cfg->sdt_state == GET_DUMP) - ioa_cfg->sdt_state = WAIT_FOR_DUMP; - } else + else ipr_unit_check_no_data(ioa_cfg); list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q); @@ -6640,48 +6424,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) return rc; } -/** - * ipr_reset_slot_reset_done - Clear PCI reset to the adapter - * @ipr_cmd: ipr command struct - * - * Description: This clears PCI reset to the adapter and delays two seconds. - * - * Return value: - * IPR_RC_JOB_RETURN - **/ -static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) -{ - ENTER; - pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset); - ipr_cmd->job_step = ipr_reset_bist_done; - ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); - LEAVE; - return IPR_RC_JOB_RETURN; -} - -/** - * ipr_reset_slot_reset - Reset the PCI slot of the adapter. - * @ipr_cmd: ipr command struct - * - * Description: This asserts PCI reset to the adapter. - * - * Return value: - * IPR_RC_JOB_RETURN - **/ -static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - struct pci_dev *pdev = ioa_cfg->pdev; - - ENTER; - pci_block_user_cfg_access(pdev); - pci_set_pcie_reset_state(pdev, pcie_warm_reset); - ipr_cmd->job_step = ipr_reset_slot_reset_done; - ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); - LEAVE; - return IPR_RC_JOB_RETURN; -} - /** * ipr_reset_allowed - Query whether or not IOA can be reset * @ioa_cfg: ioa config struct @@ -6721,7 +6463,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); } else { - ipr_cmd->job_step = ioa_cfg->reset; + ipr_cmd->job_step = ipr_reset_start_bist; rc = IPR_RC_JOB_CONTINUE; } @@ -6754,7 +6496,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd) writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg); ipr_cmd->job_step = ipr_reset_wait_to_start_bist; } else { - ipr_cmd->job_step = ioa_cfg->reset; + ipr_cmd->job_step = ipr_reset_start_bist; } ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; @@ -6849,14 +6591,12 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN; ipr_cmd->ioarcb.cmd_pkt.cdb[1] = shutdown_type; - if (shutdown_type == IPR_SHUTDOWN_NORMAL) - timeout = IPR_SHUTDOWN_TIMEOUT; + if (shutdown_type == IPR_SHUTDOWN_ABBREV) + timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT; else if (shutdown_type == IPR_SHUTDOWN_PREPARE_FOR_NORMAL) timeout = IPR_INTERNAL_TIMEOUT; - else if (ioa_cfg->dual_raid && ipr_dual_ioa_raid) - timeout = IPR_DUAL_IOA_ABBR_SHUTDOWN_TO; else - timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT; + timeout = IPR_SHUTDOWN_TIMEOUT; ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, timeout); @@ -7036,11 +6776,8 @@ static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev) struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - if (ioa_cfg->needs_warm_reset) - ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); - else - _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, - IPR_SHUTDOWN_NONE); + _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, + IPR_SHUTDOWN_NONE); spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); return PCI_ERS_RESULT_RECOVERED; } @@ -7489,7 +7226,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, unsigned long ipr_regs_pci; void __iomem *ipr_regs; int rc = PCIBIOS_SUCCESSFUL; - volatile u32 mask, uproc, interrupts; + volatile u32 mask, uproc; ENTER; @@ -7528,14 +7265,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, else ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT; - rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid); - - if (rc != PCIBIOS_SUCCESSFUL) { - dev_err(&pdev->dev, "Failed to read PCI revision ID\n"); - rc = -EIO; - goto out_scsi_host_put; - } - ipr_regs_pci = pci_resource_start(pdev, 0); rc = pci_request_regions(pdev, IPR_NAME); @@ -7604,14 +7333,9 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, * the card is in an unknown state and needs a hard reset */ mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - interrupts = readl(ioa_cfg->regs.sense_interrupt_reg); uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg); if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT)) ioa_cfg->needs_hard_reset = 1; - if (interrupts & IPR_PCII_ERROR_INTERRUPTS) - ioa_cfg->needs_hard_reset = 1; - if (interrupts & IPR_PCII_IOA_UNIT_CHECKED) - ioa_cfg->ioa_unit_checked = 1; ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg); @@ -7622,13 +7346,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto cleanup_nolog; } - if ((dev_id->driver_data & IPR_USE_PCI_WARM_RESET) || - (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { - ioa_cfg->needs_warm_reset = 1; - ioa_cfg->reset = ipr_reset_slot_reset; - } else - ioa_cfg->reset = ipr_reset_start_bist; - spin_lock(&ipr_driver_lock); list_add_tail(&ioa_cfg->queue, &ipr_ioa_head); spin_unlock(&ipr_driver_lock); @@ -7711,12 +7428,6 @@ static void __ipr_remove(struct pci_dev *pdev) ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); - while(ioa_cfg->in_reset_reload) { - spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); - wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); - spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); - } - ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL); spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); @@ -7840,12 +7551,6 @@ static void ipr_shutdown(struct pci_dev *pdev) unsigned long lock_flags = 0; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - while(ioa_cfg->in_reset_reload) { - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); - spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - } - ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); @@ -7872,22 +7577,19 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, - IPR_USE_LONG_TRANSOP_TIMEOUT }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, - IPR_USE_LONG_TRANSOP_TIMEOUT}, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, - IPR_USE_LONG_TRANSOP_TIMEOUT }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT }, @@ -7895,7 +7597,7 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, - IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET }, + IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, @@ -7925,7 +7627,6 @@ static struct pci_driver ipr_driver = { .remove = ipr_remove, .shutdown = ipr_shutdown, .err_handler = &ipr_err_handler, - .dynids.use_driver_data = 1 }; /** diff --git a/trunk/drivers/scsi/ipr.h b/trunk/drivers/scsi/ipr.h index d93156671e93..bc53d7cebe0a 100644 --- a/trunk/drivers/scsi/ipr.h +++ b/trunk/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.4.1" -#define IPR_DRIVER_DATE "(April 24, 2007)" +#define IPR_DRIVER_VERSION "2.3.2" +#define IPR_DRIVER_DATE "(March 23, 2007)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding @@ -91,7 +91,6 @@ * IOASCs */ #define IPR_IOASC_NR_INIT_CMD_REQUIRED 0x02040200 -#define IPR_IOASC_NR_IOA_RESET_REQUIRED 0x02048000 #define IPR_IOASC_SYNC_REQUIRED 0x023f0000 #define IPR_IOASC_MED_DO_NOT_REALLOC 0x03110C00 #define IPR_IOASC_HW_SEL_TIMEOUT 0x04050000 @@ -112,7 +111,6 @@ /* Driver data flags */ #define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001 -#define IPR_USE_PCI_WARM_RESET 0x00000002 #define IPR_DEFAULT_MAX_ERROR_DUMP 984 #define IPR_NUM_LOG_HCAMS 2 @@ -181,7 +179,6 @@ #define IPR_SHUTDOWN_TIMEOUT (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ) #define IPR_VSET_RW_TIMEOUT (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ) #define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) -#define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ) #define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) #define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) #define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) @@ -194,7 +191,6 @@ #define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ) #define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10) #define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ) -#define IPR_PCI_RESET_TIMEOUT (HZ / 2) #define IPR_DUMP_TIMEOUT (15 * HZ) /* @@ -606,12 +602,6 @@ struct ipr_mode_page28 { struct ipr_dev_bus_entry bus[0]; }__attribute__((packed)); -struct ipr_mode_page24 { - struct ipr_mode_page_hdr hdr; - u8 flags; -#define IPR_ENABLE_DUAL_IOA_AF 0x80 -}__attribute__((packed)); - struct ipr_ioa_vpd { struct ipr_std_inq_data std_inq_data; u8 ascii_part_num[12]; @@ -634,19 +624,6 @@ struct ipr_inquiry_page3 { u8 patch_number[4]; }__attribute__((packed)); -struct ipr_inquiry_cap { - u8 peri_qual_dev_type; - u8 page_code; - u8 reserved1; - u8 page_length; - u8 ascii_len; - u8 reserved2; - u8 sis_version[2]; - u8 cap; -#define IPR_CAP_DUAL_IOA_RAID 0x80 - u8 reserved3[15]; -}__attribute__((packed)); - #define IPR_INQUIRY_PAGE0_ENTRIES 20 struct ipr_inquiry_page0 { u8 peri_qual_dev_type; @@ -985,7 +962,6 @@ struct ipr_misc_cbs { struct ipr_ioa_vpd ioa_vpd; struct ipr_inquiry_page0 page0_data; struct ipr_inquiry_page3 page3_data; - struct ipr_inquiry_cap cap; struct ipr_mode_pages mode_pages; struct ipr_supported_device supp_dev; }; @@ -1092,10 +1068,6 @@ struct ipr_ioa_cfg { u8 allow_cmds:1; u8 allow_ml_add_del:1; u8 needs_hard_reset:1; - u8 dual_raid:1; - u8 needs_warm_reset:1; - - u8 revid; enum ipr_cache_state cache_state; u16 type; /* CCIN of the card */ @@ -1189,7 +1161,6 @@ struct ipr_ioa_cfg { struct pci_pool *ipr_cmd_pool; struct ipr_cmnd *reset_cmd; - int (*reset) (struct ipr_cmnd *); struct ata_host ata_host; char ipr_cmd_label[8]; diff --git a/trunk/drivers/scsi/libsas/sas_scsi_host.c b/trunk/drivers/scsi/libsas/sas_scsi_host.c index b4b52694497c..897a5e2c55e4 100644 --- a/trunk/drivers/scsi/libsas/sas_scsi_host.c +++ b/trunk/drivers/scsi/libsas/sas_scsi_host.c @@ -23,8 +23,6 @@ * */ -#include - #include "sas_internal.h" #include @@ -186,7 +184,7 @@ static int sas_queue_up(struct sas_task *task) list_add_tail(&task->list, &core->task_queue); core->task_queue_size += 1; spin_unlock_irqrestore(&core->task_queue_lock, flags); - wake_up_process(core->queue_thread); + up(&core->queue_thread_sema); return 0; } @@ -821,7 +819,7 @@ static void sas_queue(struct sas_ha_struct *sas_ha) struct sas_internal *i = to_sas_internal(core->shost->transportt); spin_lock_irqsave(&core->task_queue_lock, flags); - while (!kthread_should_stop() && + while (!core->queue_thread_kill && !list_empty(&core->task_queue)) { can_queue = sas_ha->lldd_queue_size - core->task_queue_size; @@ -860,6 +858,8 @@ static void sas_queue(struct sas_ha_struct *sas_ha) spin_unlock_irqrestore(&core->task_queue_lock, flags); } +static DECLARE_COMPLETION(queue_th_comp); + /** * sas_queue_thread -- The Task Collector thread * @_sas_ha: pointer to struct sas_ha @@ -867,33 +867,40 @@ static void sas_queue(struct sas_ha_struct *sas_ha) static int sas_queue_thread(void *_sas_ha) { struct sas_ha_struct *sas_ha = _sas_ha; + struct scsi_core *core = &sas_ha->core; + daemonize("sas_queue_%d", core->shost->host_no); current->flags |= PF_NOFREEZE; + complete(&queue_th_comp); + while (1) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); + down_interruptible(&core->queue_thread_sema); sas_queue(sas_ha); - if (kthread_should_stop()) + if (core->queue_thread_kill) break; } + complete(&queue_th_comp); + return 0; } int sas_init_queue(struct sas_ha_struct *sas_ha) { + int res; struct scsi_core *core = &sas_ha->core; spin_lock_init(&core->task_queue_lock); core->task_queue_size = 0; INIT_LIST_HEAD(&core->task_queue); + init_MUTEX_LOCKED(&core->queue_thread_sema); - core->queue_thread = kthread_run(sas_queue_thread, sas_ha, - "sas_queue_%d", core->shost->host_no); - if (IS_ERR(core->queue_thread)) - return PTR_ERR(core->queue_thread); - return 0; + res = kernel_thread(sas_queue_thread, sas_ha, 0); + if (res >= 0) + wait_for_completion(&queue_th_comp); + + return res < 0 ? res : 0; } void sas_shutdown_queue(struct sas_ha_struct *sas_ha) @@ -902,7 +909,10 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) struct scsi_core *core = &sas_ha->core; struct sas_task *task, *n; - kthread_stop(core->queue_thread); + init_completion(&queue_th_comp); + core->queue_thread_kill = 1; + up(&core->queue_thread_sema); + wait_for_completion(&queue_th_comp); if (!list_empty(&core->task_queue)) SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n", diff --git a/trunk/drivers/scsi/lpfc/lpfc.h b/trunk/drivers/scsi/lpfc/lpfc.h index 82e8f90c4617..a7de0bca5bdd 100644 --- a/trunk/drivers/scsi/lpfc/lpfc.h +++ b/trunk/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -27,6 +27,10 @@ struct lpfc_sli2_slim; requests */ #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact the NameServer before giving up. */ +#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */ +#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */ +#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */ + #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ #define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ @@ -240,23 +244,28 @@ struct lpfc_hba { #define FC_FABRIC 0x100 /* We are fabric attached */ #define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */ #define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/ -#define FC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */ #define FC_LOADING 0x1000 /* HBA in process of loading drvr */ #define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */ #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ #define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */ -#define FC_LOOPBACK_MODE 0x40000 /* NPort is in Loopback mode */ - /* This flag is set while issuing */ - /* INIT_LINK mailbox command */ -#define FC_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */ uint32_t fc_topology; /* link topology, from LINK INIT */ struct lpfc_stats fc_stat; - struct list_head fc_nodes; + /* These are the head/tail pointers for the bind, plogi, adisc, unmap, + * and map lists. Their counters are immediately following. + */ + struct list_head fc_plogi_list; + struct list_head fc_adisc_list; + struct list_head fc_reglogin_list; + struct list_head fc_prli_list; + struct list_head fc_nlpunmap_list; + struct list_head fc_nlpmap_list; + struct list_head fc_npr_list; + struct list_head fc_unused_list; /* Keep counters for the number of entries in each list. */ uint16_t fc_plogi_cnt; @@ -378,17 +387,13 @@ struct lpfc_hba { mempool_t *mbox_mem_pool; mempool_t *nlp_mem_pool; + struct list_head freebufList; + struct list_head ctrspbuflist; + struct list_head rnidrspbuflist; struct fc_host_statistics link_stats; }; -static inline void -lpfc_set_loopback_flag(struct lpfc_hba *phba) { - if (phba->cfg_topology == FLAGS_LOCAL_LB) - phba->fc_flag |= FC_LOOPBACK_MODE; - else - phba->fc_flag &= ~FC_LOOPBACK_MODE; -} struct rnidrsp { void *buf; diff --git a/trunk/drivers/scsi/lpfc/lpfc_attr.c b/trunk/drivers/scsi/lpfc/lpfc_attr.c index 95fe77e816f8..f247e786af99 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_attr.c +++ b/trunk/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -20,7 +20,6 @@ *******************************************************************/ #include -#include #include #include @@ -214,7 +213,6 @@ lpfc_issue_lip(struct Scsi_Host *host) int mbxstatus = MBXERR_ERROR; if ((phba->fc_flag & FC_OFFLINE_MODE) || - (phba->fc_flag & FC_BLOCK_MGMT_IO) || (phba->hba_state != LPFC_HBA_READY)) return -EPERM; @@ -237,7 +235,6 @@ lpfc_issue_lip(struct Scsi_Host *host) phba->fc_ratov * 2); } - lpfc_set_loopback_flag(phba); if (mbxstatus == MBX_TIMEOUT) pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; else @@ -250,62 +247,19 @@ lpfc_issue_lip(struct Scsi_Host *host) } static int -lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) +lpfc_selective_reset(struct lpfc_hba *phba) { struct completion online_compl; - struct lpfc_sli_ring *pring; - struct lpfc_sli *psli; int status = 0; - int cnt = 0; - int i; init_completion(&online_compl); lpfc_workq_post_event(phba, &status, &online_compl, - LPFC_EVT_OFFLINE_PREP); - wait_for_completion(&online_compl); - - if (status != 0) - return -EIO; - - psli = &phba->sli; - - for (i = 0; i < psli->num_rings; i++) { - pring = &psli->ring[i]; - /* The linkdown event takes 30 seconds to timeout. */ - while (pring->txcmplq_cnt) { - msleep(10); - if (cnt++ > 3000) { - lpfc_printf_log(phba, - KERN_WARNING, LOG_INIT, - "%d:0466 Outstanding IO when " - "bringing Adapter offline\n", - phba->brd_no); - break; - } - } - } - - init_completion(&online_compl); - lpfc_workq_post_event(phba, &status, &online_compl, type); + LPFC_EVT_OFFLINE); wait_for_completion(&online_compl); if (status != 0) return -EIO; - return 0; -} - -static int -lpfc_selective_reset(struct lpfc_hba *phba) -{ - struct completion online_compl; - int status = 0; - - status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); - - if (status != 0) - return status; - init_completion(&online_compl); lpfc_workq_post_event(phba, &status, &online_compl, LPFC_EVT_ONLINE); @@ -370,19 +324,23 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) init_completion(&online_compl); - if(strncmp(buf, "online", sizeof("online") - 1) == 0) { + if(strncmp(buf, "online", sizeof("online") - 1) == 0) lpfc_workq_post_event(phba, &status, &online_compl, LPFC_EVT_ONLINE); - wait_for_completion(&online_compl); - } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) - status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); + else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_OFFLINE); else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) - status = lpfc_do_offline(phba, LPFC_EVT_WARM_START); - else if (strncmp(buf, "error", sizeof("error") - 1) == 0) - status = lpfc_do_offline(phba, LPFC_EVT_KILL); + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_WARM_START); + else if (strncmp(buf, "error", sizeof("error") - 1) == 0) + lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_KILL); else return -EINVAL; + wait_for_completion(&online_compl); + if (!status) return strlen(buf); else @@ -687,7 +645,9 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) dev_printk(KERN_NOTICE, &phba->pcidev->dev, "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); - stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); + init_completion(&online_compl); + lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE); + wait_for_completion(&online_compl); if (stat1) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0463 lpfc_soft_wwpn attribute set failed to reinit " @@ -829,18 +789,6 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val) return -EINVAL; } -static void -lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba) -{ - struct lpfc_nodelist *ndlp; - - spin_lock_irq(phba->host->host_lock); - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) - if (ndlp->rport) - ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo; - spin_unlock_irq(phba->host->host_lock); -} - static int lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) { @@ -856,7 +804,6 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { phba->cfg_nodev_tmo = val; phba->cfg_devloss_tmo = val; - lpfc_update_rport_devloss_tmo(phba); return 0; } @@ -892,7 +839,6 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) phba->cfg_nodev_tmo = val; phba->cfg_devloss_tmo = val; phba->dev_loss_tmo_changed = 1; - lpfc_update_rport_devloss_tmo(phba); return 0; } @@ -985,10 +931,9 @@ LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology"); # 1 = 1 Gigabaud # 2 = 2 Gigabaud # 4 = 4 Gigabaud -# 8 = 8 Gigabaud -# Value range is [0,8]. Default value is 0. +# Value range is [0,4]. Default value is 0. */ -LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed"); +LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed"); /* # lpfc_fcp_class: Determines FC class to use for the FCP protocol. @@ -1013,7 +958,7 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support"); /* # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing # cr_delay (msec) or cr_count outstanding commands. cr_delay can take -# value [0,63]. cr_count can take value [1,255]. Default value of cr_delay +# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay # is 0. Default value of cr_count is 1. The cr_count feature is disabled if # cr_delay is set to 0. */ @@ -1282,11 +1227,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; int rc; - if (off > MAILBOX_CMD_SIZE) + if (off > sizeof(MAILBOX_t)) return -ERANGE; - if ((count + off) > MAILBOX_CMD_SIZE) - count = MAILBOX_CMD_SIZE - off; + if ((count + off) > sizeof(MAILBOX_t)) + count = sizeof(MAILBOX_t) - off; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; @@ -1362,12 +1307,6 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) return -EPERM; } - if (phba->fc_flag & FC_BLOCK_MGMT_IO) { - sysfs_mbox_idle(phba); - spin_unlock_irq(host->host_lock); - return -EAGAIN; - } - if ((phba->fc_flag & FC_OFFLINE_MODE) || (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){ @@ -1387,11 +1326,6 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) } if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) { - phba->sysfs_mbox.mbox->mbox_cmpl = - lpfc_sli_def_mbox_cmpl; - phba->sysfs_mbox.mbox = NULL; - } sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV; @@ -1410,7 +1344,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) phba->sysfs_mbox.offset = off + count; - if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE) + if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t)) sysfs_mbox_idle(phba); spin_unlock_irq(phba->host->host_lock); @@ -1424,7 +1358,7 @@ static struct bin_attribute sysfs_mbox_attr = { .mode = S_IRUSR | S_IWUSR, .owner = THIS_MODULE, }, - .size = MAILBOX_CMD_SIZE, + .size = sizeof(MAILBOX_t), .read = sysfs_mbox_read, .write = sysfs_mbox_write, }; @@ -1560,9 +1494,6 @@ lpfc_get_host_speed(struct Scsi_Host *shost) case LA_4GHZ_LINK: fc_host_speed(shost) = FC_PORTSPEED_4GBIT; break; - case LA_8GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_8GBIT; - break; default: fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; @@ -1615,9 +1546,6 @@ lpfc_get_stats(struct Scsi_Host *shost) unsigned long seconds; int rc = 0; - if (phba->fc_flag & FC_BLOCK_MGMT_IO) - return NULL; - pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmboxq) return NULL; @@ -1703,8 +1631,6 @@ lpfc_get_stats(struct Scsi_Host *shost) else hs->seconds_since_last_reset = seconds - psli->stats_start; - mempool_free(pmboxq, phba->mbox_mem_pool); - return hs; } @@ -1718,9 +1644,6 @@ lpfc_reset_stats(struct Scsi_Host *shost) MAILBOX_t *pmb; int rc = 0; - if (phba->fc_flag & FC_BLOCK_MGMT_IO) - return; - pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmboxq) return; @@ -1776,8 +1699,6 @@ lpfc_reset_stats(struct Scsi_Host *shost) psli->stats_start = get_seconds(); - mempool_free(pmboxq, phba->mbox_mem_pool); - return; } @@ -1785,51 +1706,67 @@ lpfc_reset_stats(struct Scsi_Host *shost) * The LPFC driver treats linkdown handling as target loss events so there * are no sysfs handlers for link_down_tmo. */ - -static struct lpfc_nodelist * -lpfc_get_node_by_target(struct scsi_target *starget) +static void +lpfc_get_starget_port_id(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; - struct lpfc_nodelist *ndlp; + uint32_t did = -1; + struct lpfc_nodelist *ndlp = NULL; spin_lock_irq(shost->host_lock); - /* Search for this, mapped, target ID */ - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && - starget->id == ndlp->nlp_sid) { - spin_unlock_irq(shost->host_lock); - return ndlp; + /* Search the mapped list for this target ID */ + list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { + if (starget->id == ndlp->nlp_sid) { + did = ndlp->nlp_DID; + break; } } spin_unlock_irq(shost->host_lock); - return NULL; -} - -static void -lpfc_get_starget_port_id(struct scsi_target *starget) -{ - struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); - fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1; + fc_starget_port_id(starget) = did; } static void lpfc_get_starget_node_name(struct scsi_target *starget) { - struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; + u64 node_name = 0; + struct lpfc_nodelist *ndlp = NULL; + + spin_lock_irq(shost->host_lock); + /* Search the mapped list for this target ID */ + list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { + if (starget->id == ndlp->nlp_sid) { + node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); + break; + } + } + spin_unlock_irq(shost->host_lock); - fc_starget_node_name(starget) = - ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0; + fc_starget_node_name(starget) = node_name; } static void lpfc_get_starget_port_name(struct scsi_target *starget) { - struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata; + u64 port_name = 0; + struct lpfc_nodelist *ndlp = NULL; + + spin_lock_irq(shost->host_lock); + /* Search the mapped list for this target ID */ + list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { + if (starget->id == ndlp->nlp_sid) { + port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); + break; + } + } + spin_unlock_irq(shost->host_lock); - fc_starget_port_name(starget) = - ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0; + fc_starget_port_name(starget) = port_name; } static void @@ -1958,8 +1895,25 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) sizeof(struct fcp_rsp) + (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64)); + switch (phba->pcidev->device) { + case PCI_DEVICE_ID_LP101: + case PCI_DEVICE_ID_BSMB: + case PCI_DEVICE_ID_ZSMB: + phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH; + break; + case PCI_DEVICE_ID_RFLY: + case PCI_DEVICE_ID_PFLY: + case PCI_DEVICE_ID_BMID: + case PCI_DEVICE_ID_ZMID: + case PCI_DEVICE_ID_TFLY: + phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH; + break; + default: + phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH; + } - lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); + if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth) + lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); return; } diff --git a/trunk/drivers/scsi/lpfc/lpfc_crtn.h b/trunk/drivers/scsi/lpfc/lpfc_crtn.h index b8c2a8862d8c..1251788ce2a3 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_crtn.h +++ b/trunk/drivers/scsi/lpfc/lpfc_crtn.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -18,8 +18,6 @@ * included with this package. * *******************************************************************/ -typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param); - struct fc_rport; void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); @@ -45,24 +43,20 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); -void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *); -void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int); -void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *); +int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int); void lpfc_set_disctmo(struct lpfc_hba *); int lpfc_can_disctmo(struct lpfc_hba *); int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *); int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *, struct lpfc_nodelist *); +int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *); void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t); -struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); -int lpfc_nlp_put(struct lpfc_nodelist *); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t); void lpfc_disc_list_loopmap(struct lpfc_hba *); void lpfc_disc_start(struct lpfc_hba *); void lpfc_disc_flush_list(struct lpfc_hba *); void lpfc_disc_timeout(unsigned long); -struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi); int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); @@ -72,7 +66,8 @@ int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *, int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *, struct serv_parm *, uint32_t); -int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp); +int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp, + int); int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_hba *); int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t); @@ -118,10 +113,7 @@ void lpfc_hba_init(struct lpfc_hba *, uint32_t *); int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); int lpfc_online(struct lpfc_hba *); -void lpfc_block_mgmt_io(struct lpfc_hba *); -void lpfc_unblock_mgmt_io(struct lpfc_hba *); -void lpfc_offline_prep(struct lpfc_hba *); -void lpfc_offline(struct lpfc_hba *); +int lpfc_offline(struct lpfc_hba *); int lpfc_sli_setup(struct lpfc_hba *); int lpfc_sli_queue_setup(struct lpfc_hba *); @@ -170,8 +162,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, struct lpfc_sli_ring *, dma_addr_t); -int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, - struct lpfc_iocbq *); +int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *, + struct lpfc_iocbq *); int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, uint64_t, lpfc_ctx_cmd); int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, @@ -180,8 +172,9 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout_handler(struct lpfc_hba *); -struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t); -struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *); +struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t); +struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t, + struct lpfc_name *); int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, uint32_t timeout); @@ -200,9 +193,6 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); /* Function prototypes. */ const char* lpfc_info(struct Scsi_Host *); -void lpfc_scan_start(struct Scsi_Host *); -int lpfc_scan_finished(struct Scsi_Host *, unsigned long); - void lpfc_get_cfgparam(struct lpfc_hba *); int lpfc_alloc_sysfs_attr(struct lpfc_hba *); void lpfc_free_sysfs_attr(struct lpfc_hba *); diff --git a/trunk/drivers/scsi/lpfc/lpfc_ct.c b/trunk/drivers/scsi/lpfc/lpfc_ct.c index 34a9e3bb2614..a51a41b7f15d 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_ct.c +++ b/trunk/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -334,22 +334,21 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) lpfc_set_disctmo(phba); + Cnt = Size > FCELSSIZE ? FCELSSIZE : Size; list_add_tail(&head, &mp->list); list_for_each_entry_safe(mp, next_mp, &head, list) { mlast = mp; - Cnt = Size > FCELSSIZE ? FCELSSIZE : Size; - Size -= Cnt; - if (!ctptr) { + if (!ctptr) ctptr = (uint32_t *) mlast->virt; - } else + else Cnt -= 16; /* subtract length of CT header */ /* Loop through entire NameServer list of DIDs */ - while (Cnt >= sizeof (uint32_t)) { + while (Cnt) { /* Get next DID from NameServer List */ CTentry = *ctptr++; @@ -443,8 +442,10 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { phba->fc_ns_retry++; /* CT command is being retried */ - ndlp = lpfc_findnode_did(phba, NameServer_DID); - if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { + ndlp = + lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, + NameServer_DID); + if (ndlp) { if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { goto out; @@ -728,7 +729,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba, uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; - ndlp = lpfc_findnode_did(phba, FDMI_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* FDMI rsp failed */ lpfc_printf_log(phba, @@ -1038,9 +1039,6 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) case LA_4GHZ_LINK: ae->un.PortSpeed = HBA_PORTSPEED_4GBIT; break; - case LA_8GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_8GBIT; - break; default: ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN; @@ -1163,7 +1161,7 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba) { struct lpfc_nodelist *ndlp; - ndlp = lpfc_findnode_did(phba, FDMI_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID); if (ndlp) { if (init_utsname()->nodename[0] != '\0') { lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA); diff --git a/trunk/drivers/scsi/lpfc/lpfc_disc.h b/trunk/drivers/scsi/lpfc/lpfc_disc.h index 498059f3f7f4..9766f909c9c6 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_disc.h +++ b/trunk/drivers/scsi/lpfc/lpfc_disc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -31,7 +31,6 @@ /* worker thread events */ enum lpfc_work_type { LPFC_EVT_ONLINE, - LPFC_EVT_OFFLINE_PREP, LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL, @@ -69,6 +68,7 @@ struct lpfc_nodelist { uint16_t nlp_maxframe; /* Max RCV frame size */ uint8_t nlp_class_sup; /* Supported Classes */ uint8_t nlp_retry; /* used for ELS retries */ + uint8_t nlp_disc_refcnt; /* used for DSM */ uint8_t nlp_fcp_info; /* class info, bits 0-3 */ #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ @@ -79,10 +79,20 @@ struct lpfc_nodelist { struct lpfc_work_evt els_retry_evt; unsigned long last_ramp_up_time; /* jiffy of last ramp up */ unsigned long last_q_full_time; /* jiffy of last queue full */ - struct kref kref; }; /* Defines for nlp_flag (uint32) */ +#define NLP_NO_LIST 0x0 /* Indicates immediately free node */ +#define NLP_UNUSED_LIST 0x1 /* Flg to indicate node will be freed */ +#define NLP_PLOGI_LIST 0x2 /* Flg to indicate sent PLOGI */ +#define NLP_ADISC_LIST 0x3 /* Flg to indicate sent ADISC */ +#define NLP_REGLOGIN_LIST 0x4 /* Flg to indicate sent REG_LOGIN */ +#define NLP_PRLI_LIST 0x5 /* Flg to indicate sent PRLI */ +#define NLP_UNMAPPED_LIST 0x6 /* Node is now unmapped */ +#define NLP_MAPPED_LIST 0x7 /* Node is now mapped */ +#define NLP_NPR_LIST 0x8 /* Node is in NPort Recovery state */ +#define NLP_JUST_DQ 0x9 /* just deque ndlp in lpfc_nlp_list */ +#define NLP_LIST_MASK 0xf /* mask to see what list node is on */ #define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */ #define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */ #define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */ @@ -98,8 +108,20 @@ struct lpfc_nodelist { ACC */ #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from NPR list */ +#define NLP_DELAY_REMOVE 0x4000000 /* Defer removal till end of DSM */ #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ +/* Defines for list searchs */ +#define NLP_SEARCH_MAPPED 0x1 /* search mapped */ +#define NLP_SEARCH_UNMAPPED 0x2 /* search unmapped */ +#define NLP_SEARCH_PLOGI 0x4 /* search plogi */ +#define NLP_SEARCH_ADISC 0x8 /* search adisc */ +#define NLP_SEARCH_REGLOGIN 0x10 /* search reglogin */ +#define NLP_SEARCH_PRLI 0x20 /* search prli */ +#define NLP_SEARCH_NPR 0x40 /* search npr */ +#define NLP_SEARCH_UNUSED 0x80 /* search mapped */ +#define NLP_SEARCH_ALL 0xff /* search all lists */ + /* There are 4 different double linked lists nodelist entries can reside on. * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used * when Link Up discovery or Registered State Change Notification (RSCN) diff --git a/trunk/drivers/scsi/lpfc/lpfc_els.c b/trunk/drivers/scsi/lpfc/lpfc_els.c index 638b3cd677bd..a5f33a0dd4e7 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_els.c +++ b/trunk/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -182,7 +182,6 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); icmd->un.elsreq64.remoteID = did; /* DID */ icmd->ulpCommand = CMD_ELS_REQUEST64_CR; - icmd->ulpTimeout = phba->fc_ratov * 2; } else { icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64); icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX; @@ -209,9 +208,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, } /* Save for completion so we can release these resources */ - elsiocb->context1 = lpfc_nlp_get(ndlp); - elsiocb->context2 = pcmd; - elsiocb->context3 = pbuflist; + elsiocb->context1 = (uint8_t *) ndlp; + elsiocb->context2 = (uint8_t *) pcmd; + elsiocb->context3 = (uint8_t *) pbuflist; elsiocb->retry = retry; elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; @@ -223,16 +222,16 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, /* Xmit ELS command to remote NPORT */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0116 Xmit ELS command x%x to remote " - "NPORT x%x I/O tag: x%x, HBA state: x%x\n", + "NPORT x%x Data: x%x x%x\n", phba->brd_no, elscmd, - did, elsiocb->iotag, phba->hba_state); + did, icmd->ulpIoTag, phba->hba_state); } else { /* Xmit ELS response to remote NPORT */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0117 Xmit ELS response x%x to remote " - "NPORT x%x I/O tag: x%x, size: x%x\n", + "NPORT x%x Data: x%x x%x\n", phba->brd_no, elscmd, - ndlp->nlp_DID, elsiocb->iotag, cmdSize); + ndlp->nlp_DID, icmd->ulpIoTag, cmdSize); } return elsiocb; @@ -305,7 +304,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, goto fail_free_mbox; mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; - mbox->context2 = lpfc_nlp_get(ndlp); + mbox->context2 = ndlp; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); if (rc == MBX_NOT_FINISHED) @@ -314,7 +313,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, return 0; fail_issue_reg_login: - lpfc_nlp_put(ndlp); mp = (struct lpfc_dmabuf *) mbox->context1; lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); @@ -370,9 +368,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, mempool_free(mbox, phba->mbox_mem_pool); goto fail; } - lpfc_nlp_put(ndlp); + mempool_free(ndlp, phba->nlp_mem_pool); - ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID); if (!ndlp) { /* * Cannot find existing Fabric ndlp, so allocate a @@ -389,11 +387,12 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, sizeof(struct lpfc_name)); memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name)); - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; } else { /* This side will wait for the PLOGI */ - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); } spin_lock_irq(phba->host->host_lock); @@ -408,8 +407,8 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, } static void -lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) +lpfc_cmpl_els_flogi(struct lpfc_hba * phba, + struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb) { IOCB_t *irsp = &rspiocb->iocb; struct lpfc_nodelist *ndlp = cmdiocb->context1; @@ -419,7 +418,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(phba)) { - lpfc_nlp_put(ndlp); + lpfc_nlp_remove(phba, ndlp); goto out; } @@ -434,12 +433,13 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); spin_unlock_irq(phba->host->host_lock); - /* If private loop, then allow max outstanding els to be + /* If private loop, then allow max outstandting els to be * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no * alpa map would take too long otherwise. */ if (phba->alpa_map[0] == 0) { - phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; + phba->cfg_discovery_threads = + LPFC_MAX_DISC_THREADS; } /* FLOGI failure */ @@ -484,7 +484,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } flogifail: - lpfc_nlp_put(ndlp); + lpfc_nlp_remove(phba, ndlp); if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && @@ -582,8 +582,24 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba) icmd = &iocb->iocb; if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { ndlp = (struct lpfc_nodelist *)(iocb->context1); - if (ndlp && (ndlp->nlp_DID == Fabric_DID)) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + if (ndlp && (ndlp->nlp_DID == Fabric_DID)) { + list_del(&iocb->list); + pring->txcmplq_cnt--; + + if ((icmd->un.elsreq64.bdl.ulpIoTag32)) { + lpfc_sli_issue_abort_iotag32 + (phba, pring, iocb); + } + if (iocb->iocb_cmpl) { + icmd->ulpStatus = IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = + IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); + (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, iocb); + } } } spin_unlock_irq(phba->host->host_lock); @@ -592,12 +608,12 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba) } int -lpfc_initial_flogi(struct lpfc_hba *phba) +lpfc_initial_flogi(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp; /* First look for the Fabric ndlp */ - ndlp = lpfc_findnode_did(phba, Fabric_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID); if (!ndlp) { /* Cannot find existing Fabric ndlp, so allocate a new one */ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); @@ -605,10 +621,10 @@ lpfc_initial_flogi(struct lpfc_hba *phba) return 0; lpfc_nlp_init(phba, ndlp, Fabric_DID); } else { - lpfc_dequeue_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); } if (lpfc_issue_els_flogi(phba, ndlp, 0)) { - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); } return 1; } @@ -637,7 +653,7 @@ lpfc_more_plogi(struct lpfc_hba * phba) } static struct lpfc_nodelist * -lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, +lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, struct lpfc_nodelist *ndlp) { struct lpfc_nodelist *new_ndlp; @@ -654,12 +670,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, lp = (uint32_t *) prsp->virt; sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); - memset(name, 0, sizeof(struct lpfc_name)); + memset(name, 0, sizeof (struct lpfc_name)); - /* Now we find out if the NPort we are logging into, matches the WWPN + /* Now we to find out if the NPort we are logging into, matches the WWPN * we have for that ndlp. If not, we have some work to do. */ - new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName); + new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); if (new_ndlp == ndlp) return ndlp; @@ -679,15 +695,18 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, lpfc_unreg_rpi(phba, new_ndlp); new_ndlp->nlp_DID = ndlp->nlp_DID; new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; - lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state); + new_ndlp->nlp_state = ndlp->nlp_state; + lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK); /* Move this back to NPR list */ - if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) - lpfc_drop_node(phba, ndlp); + if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } else { lpfc_unreg_rpi(phba, ndlp); ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); } return new_ndlp; } @@ -701,11 +720,13 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_dmabuf *prsp; int disc, rc, did, type; + /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; irsp = &rspiocb->iocb; - ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, + irsp->un.elsreq64.remoteID); if (!ndlp) goto out; @@ -1333,7 +1354,7 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_SCR); if (!elsiocb) { - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); return 1; } @@ -1352,12 +1373,12 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) spin_lock_irq(phba->host->host_lock); if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); lpfc_els_free_iocb(phba, elsiocb); return 1; } spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); return 0; } @@ -1386,7 +1407,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_RNID); if (!elsiocb) { - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); return 1; } @@ -1407,7 +1428,7 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name)); memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); - if ((ondlp = lpfc_findnode_did(phba, nportid))) { + if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) { memcpy(&fp->OportName, &ondlp->nlp_portname, sizeof (struct lpfc_name)); memcpy(&fp->OnodeName, &ondlp->nlp_nodename, @@ -1419,12 +1440,12 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) spin_lock_irq(phba->host->host_lock); if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); lpfc_els_free_iocb(phba, elsiocb); return 1; } spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_put(ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); return 0; } @@ -1533,25 +1554,29 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) case ELS_CMD_PLOGI: if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); } break; case ELS_CMD_ADISC: if (!lpfc_issue_els_adisc(phba, ndlp, retry)) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); } break; case ELS_CMD_PRLI: if (!lpfc_issue_els_prli(phba, ndlp, retry)) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); + ndlp->nlp_state = NLP_STE_PRLI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); } break; case ELS_CMD_LOGO: if (!lpfc_issue_els_logo(phba, ndlp, retry)) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); } break; } @@ -1589,12 +1614,12 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, cmd = *elscmd++; } - if (ndlp) + if(ndlp) did = ndlp->nlp_DID; else { /* We should only hit this case for retrying PLOGI */ did = irsp->un.elsreq64.remoteID; - ndlp = lpfc_findnode_did(phba, did); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); if (!ndlp && (cmd != ELS_CMD_PLOGI)) return 1; } @@ -1721,7 +1746,8 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, ndlp->nlp_flag |= NLP_DELAY_TMO; ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_last_elscmd = cmd; return 1; @@ -1733,24 +1759,27 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, case ELS_CMD_PLOGI: if (ndlp) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, - NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); } lpfc_issue_els_plogi(phba, did, cmdiocb->retry); return 1; case ELS_CMD_ADISC: ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_PRLI: ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); + ndlp->nlp_state = NLP_STE_PRLI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); return 1; case ELS_CMD_LOGO: ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); return 1; } @@ -1767,14 +1796,10 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } int -lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) +lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb) { struct lpfc_dmabuf *buf_ptr, *buf_ptr1; - if (elsiocb->context1) { - lpfc_nlp_put(elsiocb->context1); - elsiocb->context1 = NULL; - } /* context2 = cmd, context2->next = rsp, context3 = bpl */ if (elsiocb->context2) { buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; @@ -1818,7 +1843,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, switch (ndlp->nlp_state) { case NLP_STE_UNUSED_NODE: /* node is just allocated */ - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); break; case NLP_STE_NPR_NODE: /* NPort Recovery mode */ lpfc_unreg_rpi(phba, ndlp); @@ -1831,8 +1856,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } static void -lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) +lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_iocbq * rspiocb) { IOCB_t *irsp; struct lpfc_nodelist *ndlp; @@ -1847,14 +1872,14 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check to see if link went down during discovery */ - if (lpfc_els_chk_latt(phba) || !ndlp) { + if ((lpfc_els_chk_latt(phba)) || !ndlp) { if (mbox) { mp = (struct lpfc_dmabuf *) mbox->context1; if (mp) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free( mbox, phba->mbox_mem_pool); } goto out; } @@ -1874,15 +1899,15 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { lpfc_unreg_rpi(phba, ndlp); mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; - mbox->context2 = lpfc_nlp_get(ndlp); + mbox->context2 = ndlp; ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); + ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST); if (lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { goto out; } - lpfc_nlp_put(ndlp); /* NOTE: we should have messages for unsuccessful reglogin */ } else { @@ -1892,7 +1917,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) { if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); ndlp = NULL; } } @@ -1987,16 +2012,15 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, return 1; } - if (newnode) { - lpfc_nlp_put(ndlp); + if (newnode) elsiocb->context1 = NULL; - } /* Xmit ELS ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, " - "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n", - phba->brd_no, elsiocb->iotag, + "%d:0128 Xmit ELS ACC response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); @@ -2053,9 +2077,10 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, /* Xmit ELS RJT response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - phba->brd_no, rejectError, elsiocb->iotag, + "%d:0129 Xmit ELS RJT x%x response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + rejectError, elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); @@ -2094,18 +2119,18 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri */ - /* Xmit ADISC ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0130 Xmit ADISC ACC response iotag x%x xri: " - "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n", - phba->brd_no, elsiocb->iotag, + "%d:0130 Xmit ADISC ACC response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; @@ -2130,8 +2155,8 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, } int -lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, - struct lpfc_nodelist *ndlp) +lpfc_els_rsp_prli_acc(struct lpfc_hba * phba, + struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) { PRLI *npr; lpfc_vpd_t *vpd; @@ -2153,18 +2178,18 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri */ - /* Xmit PRLI ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - phba->brd_no, elsiocb->iotag, + "%d:0131 Xmit PRLI ACC response tag x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); @@ -2207,8 +2232,9 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, } static int -lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, - struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) +lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba, + uint8_t format, + struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) { RNID *rn; IOCB_t *icmd; @@ -2233,17 +2259,17 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, if (!elsiocb) return 1; - icmd = &elsiocb->iocb; - oldcmd = &oldiocb->iocb; - icmd->ulpContext = oldcmd->ulpContext; /* Xri */ - /* Xmit RNID ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0132 Xmit RNID ACC response tag x%x " - "xri x%x\n", - phba->brd_no, elsiocb->iotag, + "Data: x%x\n", + phba->brd_no, + elsiocb->iocb.ulpIoTag, elsiocb->iocb.ulpContext); + icmd = &elsiocb->iocb; + oldcmd = &oldiocb->iocb; + icmd->ulpContext = oldcmd->ulpContext; /* Xri */ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; @@ -2275,7 +2301,6 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; - lpfc_nlp_put(ndlp); elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, * it could be freed */ @@ -2290,31 +2315,32 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, } int -lpfc_els_disc_adisc(struct lpfc_hba *phba) +lpfc_els_disc_adisc(struct lpfc_hba * phba) { int sentadisc; struct lpfc_nodelist *ndlp, *next_ndlp; sentadisc = 0; - /* go thru NPR nodes and issue any remaining ELS ADISCs */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_NPR_NODE && - (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && - (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(phba->host->host_lock); - ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); - lpfc_issue_els_adisc(phba, ndlp, 0); - sentadisc++; - phba->num_disc_nodes++; - if (phba->num_disc_nodes >= - phba->cfg_discovery_threads) { - spin_lock_irq(phba->host->host_lock); - phba->fc_flag |= FC_NLP_MORE; - spin_unlock_irq(phba->host->host_lock); - break; + /* go thru NPR list and issue any remaining ELS ADISCs */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { + if (ndlp->nlp_flag & NLP_NPR_ADISC) { + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + ndlp->nlp_prev_state = ndlp->nlp_state; + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, + NLP_ADISC_LIST); + lpfc_issue_els_adisc(phba, ndlp, 0); + sentadisc++; + phba->num_disc_nodes++; + if (phba->num_disc_nodes >= + phba->cfg_discovery_threads) { + spin_lock_irq(phba->host->host_lock); + phba->fc_flag |= FC_NLP_MORE; + spin_unlock_irq(phba->host->host_lock); + break; + } } } } @@ -2334,22 +2360,24 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba) sentplogi = 0; /* go thru NPR list and issue any remaining ELS PLOGIs */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_NPR_NODE && - (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && - (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && - (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) { - ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); - lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); - sentplogi++; - phba->num_disc_nodes++; - if (phba->num_disc_nodes >= - phba->cfg_discovery_threads) { - spin_lock_irq(phba->host->host_lock); - phba->fc_flag |= FC_NLP_MORE; - spin_unlock_irq(phba->host->host_lock); - break; + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) && + (!(ndlp->nlp_flag & NLP_DELAY_TMO))) { + if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { + ndlp->nlp_prev_state = ndlp->nlp_state; + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); + lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); + sentplogi++; + phba->num_disc_nodes++; + if (phba->num_disc_nodes >= + phba->cfg_discovery_threads) { + spin_lock_irq(phba->host->host_lock); + phba->fc_flag |= FC_NLP_MORE; + spin_unlock_irq(phba->host->host_lock); + break; + } } } } @@ -2451,30 +2479,42 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) } static int -lpfc_rscn_recovery_check(struct lpfc_hba *phba) +lpfc_rscn_recovery_check(struct lpfc_hba * phba) { - struct lpfc_nodelist *ndlp = NULL; + struct lpfc_nodelist *ndlp = NULL, *next_ndlp; + struct list_head *listp; + struct list_head *node_list[7]; + int i; /* Look at all nodes effected by pending RSCNs and move - * them to NPR state. + * them to NPR list. */ - - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE || - lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0) + node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ + node_list[1] = &phba->fc_nlpmap_list; + node_list[2] = &phba->fc_nlpunmap_list; + node_list[3] = &phba->fc_prli_list; + node_list[4] = &phba->fc_reglogin_list; + node_list[5] = &phba->fc_adisc_list; + node_list[6] = &phba->fc_plogi_list; + for (i = 0; i < 7; i++) { + listp = node_list[i]; + if (list_empty(listp)) continue; - lpfc_disc_state_machine(phba, ndlp, NULL, + list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { + if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) + continue; + + lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RECOVERY); - /* - * Make sure NLP_DELAY_TMO is NOT running after a device - * recovery event. - */ - if (ndlp->nlp_flag & NLP_DELAY_TMO) - lpfc_cancel_retry_delay_tmo(phba, ndlp); + /* Make sure NLP_DELAY_TMO is NOT running + * after a device recovery event. + */ + if (ndlp->nlp_flag & NLP_DELAY_TMO) + lpfc_cancel_retry_delay_tmo(phba, ndlp); + } } - return 0; } @@ -2599,8 +2639,8 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) /* To process RSCN, first compare RSCN data with NameServer */ phba->fc_ns_retry = 0; - ndlp = lpfc_findnode_did(phba, NameServer_DID); - if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID); + if (ndlp) { /* Good ndlp, issue CT Request to NameServer */ if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { /* Wait for NameServer query cmpl before we can @@ -2610,7 +2650,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) } else { /* If login to NameServer does not exist, issue one */ /* Good status, issue PLOGI to NameServer */ - ndlp = lpfc_findnode_did(phba, NameServer_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); if (ndlp) { /* Wait for NameServer login cmpl before we can continue */ @@ -2624,7 +2664,8 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) lpfc_nlp_init(phba, ndlp, NameServer_DID); ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, NameServer_DID, 0); /* Wait for NameServer login cmpl before we can continue */ @@ -2693,9 +2734,8 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); - lpfc_set_loopback_flag(phba); if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free( mbox, phba->mbox_mem_pool); } return 1; } else if (rc > 0) { /* greater than */ @@ -2760,8 +2800,8 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, } static int -lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_nodelist *ndlp) +lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_nodelist * ndlp) { struct ls_rjt stat; @@ -2775,7 +2815,7 @@ lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } static void -lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { struct lpfc_sli *psli; struct lpfc_sli_ring *pring; @@ -2798,15 +2838,14 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->context2 = NULL; if (mb->mbxStatus) { - mempool_free(pmb, phba->mbox_mem_pool); + mempool_free( pmb, phba->mbox_mem_pool); return; } cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); - mempool_free(pmb, phba->mbox_mem_pool); + mempool_free( pmb, phba->mbox_mem_pool); elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, ndlp->nlp_DID, ELS_CMD_ACC); - lpfc_nlp_put(ndlp); if (!elsiocb) return; @@ -2836,15 +2875,15 @@ 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 xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - phba->brd_no, elsiocb->iotag, + "%d:0118 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, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); } @@ -2884,14 +2923,13 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, lpfc_read_lnk_stat(phba, mbox); mbox->context1 = (void *)((unsigned long)cmdiocb->iocb.ulpContext); - mbox->context2 = lpfc_nlp_get(ndlp); + mbox->context2 = ndlp; mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; if (lpfc_sli_issue_mbox (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { /* Mbox completion will send ELS Response */ return 0; } - lpfc_nlp_put(ndlp); mempool_free(mbox, phba->mbox_mem_pool); } } @@ -2946,9 +2984,10 @@ 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 xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - phba->brd_no, elsiocb->iotag, + "%d:0120 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, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); @@ -3052,8 +3091,8 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, /* Log back into the node before sending the FARP. */ if (fp->Rflags & FARP_REQUEST_PLOGI) { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, - NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } @@ -3130,15 +3169,14 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, */ list_for_each_entry_safe(ndlp, next_ndlp, - &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state != NLP_STE_NPR_NODE) - continue; + &phba->fc_npr_list, nlp_listp) { + if (ndlp->nlp_type & NLP_FABRIC) { /* * Clean up old Fabric, Nameserver and * other NLP_FABRIC logins */ - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { /* Fail outstanding I/O now since this * device is marked for PLOGI @@ -3155,22 +3193,20 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* Discovery not needed, * move the nodes to their original state. */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, - nlp_listp) { - if (ndlp->nlp_state != NLP_STE_NPR_NODE) - continue; + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { switch (ndlp->nlp_prev_state) { case NLP_STE_UNMAPPED_NODE: ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, - NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); break; case NLP_STE_MAPPED_NODE: ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, - NLP_STE_MAPPED_NODE); + ndlp->nlp_state = NLP_STE_MAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); break; default: @@ -3210,8 +3246,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) struct lpfc_iocbq *tmp_iocb, *piocb; IOCB_t *cmd = NULL; struct lpfc_dmabuf *pcmd; + struct list_head *dlp; uint32_t *elscmd; - uint32_t els_command=0; + uint32_t els_command; uint32_t timeout; uint32_t remote_ID; @@ -3226,20 +3263,17 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) timeout = (uint32_t)(phba->fc_ratov << 1); pring = &phba->sli.ring[LPFC_ELS_RING]; + dlp = &pring->txcmplq; list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { cmd = &piocb->iocb; - if ((piocb->iocb_flag & LPFC_IO_LIBDFC) || - (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) || - (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) { + if (piocb->iocb_flag & LPFC_IO_LIBDFC) { continue; } pcmd = (struct lpfc_dmabuf *) piocb->context2; - if (pcmd) { - elscmd = (uint32_t *) (pcmd->virt); - els_command = *elscmd; - } + elscmd = (uint32_t *) (pcmd->virt); + els_command = *elscmd; if ((els_command == ELS_CMD_FARP) || (els_command == ELS_CMD_FARPR)) { @@ -3255,10 +3289,19 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) continue; } + list_del(&piocb->list); + pring->txcmplq_cnt--; + if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { struct lpfc_nodelist *ndlp; - ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext); + spin_unlock_irq(phba->host->host_lock); + ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext); + spin_lock_irq(phba->host->host_lock); remote_ID = ndlp->nlp_DID; + if (cmd->un.elsreq64.bdl.ulpIoTag32) { + lpfc_sli_issue_abort_iotag32(phba, + pring, piocb); + } } else { remote_ID = cmd->un.elsreq64.remoteID; } @@ -3270,7 +3313,17 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) phba->brd_no, els_command, remote_ID, cmd->ulpCommand, cmd->ulpIoTag); - lpfc_sli_issue_abort_iotag(phba, pring, piocb); + /* + * The iocb has timed out; abort it. + */ + if (piocb->iocb_cmpl) { + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); + (piocb->iocb_cmpl) (phba, piocb, piocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, piocb); } if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout); @@ -3279,13 +3332,16 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) } void -lpfc_els_flush_cmd(struct lpfc_hba *phba) +lpfc_els_flush_cmd(struct lpfc_hba * phba) { - LIST_HEAD(completions); - struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; + struct lpfc_sli_ring *pring; struct lpfc_iocbq *tmp_iocb, *piocb; IOCB_t *cmd = NULL; + struct lpfc_dmabuf *pcmd; + uint32_t *elscmd; + uint32_t els_command; + pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { cmd = &piocb->iocb; @@ -3295,15 +3351,29 @@ lpfc_els_flush_cmd(struct lpfc_hba *phba) } /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ - if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || - cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || - cmd->ulpCommand == CMD_CLOSE_XRI_CN || - cmd->ulpCommand == CMD_ABORT_XRI_CN) + if ((cmd->ulpCommand == CMD_QUE_RING_BUF_CN) || + (cmd->ulpCommand == CMD_QUE_RING_BUF64_CN) || + (cmd->ulpCommand == CMD_CLOSE_XRI_CN) || + (cmd->ulpCommand == CMD_ABORT_XRI_CN)) { continue; + } - list_move_tail(&piocb->list, &completions); - pring->txq_cnt--; + pcmd = (struct lpfc_dmabuf *) piocb->context2; + elscmd = (uint32_t *) (pcmd->virt); + els_command = *elscmd; + list_del(&piocb->list); + pring->txcmplq_cnt--; + + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + + if (piocb->iocb_cmpl) { + spin_unlock_irq(phba->host->host_lock); + (piocb->iocb_cmpl) (phba, piocb, piocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, piocb); } list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { @@ -3312,24 +3382,24 @@ lpfc_els_flush_cmd(struct lpfc_hba *phba) if (piocb->iocb_flag & LPFC_IO_LIBDFC) { continue; } + pcmd = (struct lpfc_dmabuf *) piocb->context2; + elscmd = (uint32_t *) (pcmd->virt); + els_command = *elscmd; - lpfc_sli_issue_abort_iotag(phba, pring, piocb); - } - spin_unlock_irq(phba->host->host_lock); - - while(!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &piocb->iocb; list_del(&piocb->list); + pring->txcmplq_cnt--; + + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; if (piocb->iocb_cmpl) { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); (piocb->iocb_cmpl) (phba, piocb, piocb); + spin_lock_irq(phba->host->host_lock); } else lpfc_sli_release_iocbq(phba, piocb); } - + spin_unlock_irq(phba->host->host_lock); return; } @@ -3398,7 +3468,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, } did = icmd->un.rcvels.remoteID; - ndlp = lpfc_findnode_did(phba, did); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); if (!ndlp) { /* Cannot find existing Fabric ndlp, so allocate a new one */ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); @@ -3414,13 +3484,12 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { ndlp->nlp_type |= NLP_FABRIC; } - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + ndlp->nlp_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); } phba->fc_stat.elsRcvFrame++; - if (elsiocb->context1) - lpfc_nlp_put(elsiocb->context1); - elsiocb->context1 = lpfc_nlp_get(ndlp); + elsiocb->context1 = ndlp; elsiocb->context2 = mp; if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { @@ -3444,8 +3513,9 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, case ELS_CMD_FLOGI: phba->fc_stat.elsRcvFLOGI++; lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; case ELS_CMD_LOGO: phba->fc_stat.elsRcvLOGO++; @@ -3466,8 +3536,9 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, case ELS_CMD_RSCN: phba->fc_stat.elsRcvRSCN++; lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; case ELS_CMD_ADISC: phba->fc_stat.elsRcvADISC++; @@ -3508,26 +3579,30 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, case ELS_CMD_LIRR: phba->fc_stat.elsRcvLIRR++; lpfc_els_rcv_lirr(phba, elsiocb, ndlp); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; case ELS_CMD_RPS: phba->fc_stat.elsRcvRPS++; lpfc_els_rcv_rps(phba, elsiocb, ndlp); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; case ELS_CMD_RPL: phba->fc_stat.elsRcvRPL++; lpfc_els_rcv_rpl(phba, elsiocb, ndlp); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; case ELS_CMD_RNID: phba->fc_stat.elsRcvRNID++; lpfc_els_rcv_rnid(phba, elsiocb, ndlp); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; default: /* Unsupported ELS command, reject */ @@ -3537,8 +3612,9 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, lpfc_printf_log(phba, KERN_ERR, LOG_ELS, "%d:0115 Unknown ELS command x%x received from " "NPORT x%x\n", phba->brd_no, cmd, did); - if (newnode) - lpfc_drop_node(phba, ndlp); + if (newnode) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } break; } @@ -3551,8 +3627,6 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp); } - lpfc_nlp_put(elsiocb->context1); - elsiocb->context1 = NULL; if (elsiocb->context2) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); diff --git a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c index 61caa8d379e2..c39564e85e94 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -109,9 +109,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) return; } - if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) - return; - name = (uint8_t *)&ndlp->nlp_portname; phba = ndlp->nlp_phba; @@ -150,17 +147,11 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ndlp->nlp_state, ndlp->nlp_rpi); } - if (!(phba->fc_flag & FC_UNLOADING) && - !(ndlp->nlp_flag & NLP_DELAY_TMO) && - !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && - (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) + ndlp->rport = NULL; + rdata->pnode = NULL; + + if (!(phba->fc_flag & FC_UNLOADING)) lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM); - else { - rdata->pnode = NULL; - ndlp->rport = NULL; - lpfc_nlp_put(ndlp); - put_device(&rport->dev); - } return; } @@ -191,35 +182,29 @@ lpfc_work_list_done(struct lpfc_hba * phba) *(int *)(evtp->evt_arg1) = 0; complete((struct completion *)(evtp->evt_arg2)); break; - case LPFC_EVT_OFFLINE_PREP: - if (phba->hba_state >= LPFC_LINK_DOWN) - lpfc_offline_prep(phba); - *(int *)(evtp->evt_arg1) = 0; - complete((struct completion *)(evtp->evt_arg2)); - break; case LPFC_EVT_OFFLINE: - lpfc_offline(phba); + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); lpfc_sli_brdrestart(phba); *(int *)(evtp->evt_arg1) = - lpfc_sli_brdready(phba, HS_FFRDY | HS_MBRDY); - lpfc_unblock_mgmt_io(phba); + lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY); complete((struct completion *)(evtp->evt_arg2)); break; case LPFC_EVT_WARM_START: - lpfc_offline(phba); + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); lpfc_reset_barrier(phba); lpfc_sli_brdreset(phba); lpfc_hba_down_post(phba); *(int *)(evtp->evt_arg1) = lpfc_sli_brdready(phba, HS_MBRDY); - lpfc_unblock_mgmt_io(phba); complete((struct completion *)(evtp->evt_arg2)); break; case LPFC_EVT_KILL: - lpfc_offline(phba); + if (phba->hba_state >= LPFC_LINK_DOWN) + lpfc_offline(phba); *(int *)(evtp->evt_arg1) = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); - lpfc_unblock_mgmt_io(phba); complete((struct completion *)(evtp->evt_arg2)); break; } @@ -374,12 +359,13 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2, } int -lpfc_linkdown(struct lpfc_hba *phba) +lpfc_linkdown(struct lpfc_hba * phba) { struct lpfc_sli *psli; struct lpfc_nodelist *ndlp, *next_ndlp; - LPFC_MBOXQ_t *mb; - int rc; + struct list_head *listp, *node_list[7]; + LPFC_MBOXQ_t *mb; + int rc, i; psli = &phba->sli; /* sysfs or selective reset may call this routine to clean up */ @@ -411,16 +397,31 @@ lpfc_linkdown(struct lpfc_hba *phba) /* Cleanup any outstanding ELS commands */ lpfc_els_flush_cmd(phba); - /* - * Issue a LINK DOWN event to all nodes. - */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { - /* free any ndlp's on unused list */ - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) - lpfc_drop_node(phba, ndlp); - else /* otherwise, force node recovery. */ + /* Issue a LINK DOWN event to all nodes */ + node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ + node_list[1] = &phba->fc_nlpmap_list; + node_list[2] = &phba->fc_nlpunmap_list; + node_list[3] = &phba->fc_prli_list; + node_list[4] = &phba->fc_reglogin_list; + node_list[5] = &phba->fc_adisc_list; + node_list[6] = &phba->fc_plogi_list; + for (i = 0; i < 7; i++) { + listp = node_list[i]; + if (list_empty(listp)) + continue; + + list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { + rc = lpfc_disc_state_machine(phba, ndlp, NULL, - NLP_EVT_DEVICE_RECOVERY); + NLP_EVT_DEVICE_RECOVERY); + + } + } + + /* free any ndlp's on unused list */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, + nlp_listp) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } /* Setup myDID for link up if we are in pt2pt mode */ @@ -451,9 +452,11 @@ lpfc_linkdown(struct lpfc_hba *phba) } static int -lpfc_linkup(struct lpfc_hba *phba) +lpfc_linkup(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp, *next_ndlp; + struct list_head *listp, *node_list[7]; + int i; fc_host_post_event(phba->host, fc_get_event_number(), FCH_EVT_LINKUP, 0); @@ -467,20 +470,29 @@ lpfc_linkup(struct lpfc_hba *phba) spin_unlock_irq(phba->host->host_lock); - if (phba->fc_flag & FC_LBIT) { - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) { + node_list[0] = &phba->fc_plogi_list; + node_list[1] = &phba->fc_adisc_list; + node_list[2] = &phba->fc_reglogin_list; + node_list[3] = &phba->fc_prli_list; + node_list[4] = &phba->fc_nlpunmap_list; + node_list[5] = &phba->fc_nlpmap_list; + node_list[6] = &phba->fc_npr_list; + for (i = 0; i < 7; i++) { + listp = node_list[i]; + if (list_empty(listp)) + continue; + + list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) { + if (phba->fc_flag & FC_LBIT) { if (ndlp->nlp_type & NLP_FABRIC) { - /* - * On Linkup its safe to clean up the + /* On Linkup its safe to clean up the * ndlp from Fabric connections. */ - lpfc_nlp_set_state(phba, ndlp, - NLP_STE_UNUSED_NODE); + lpfc_nlp_list(phba, ndlp, + NLP_UNUSED_LIST); } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { - /* - * Fail outstanding IO now since - * device is marked for PLOGI. + /* Fail outstanding IO now since device + * is marked for PLOGI. */ lpfc_unreg_rpi(phba, ndlp); } @@ -489,10 +501,9 @@ lpfc_linkup(struct lpfc_hba *phba) } /* free any ndlp's on unused list */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, - nlp_listp) { - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) - lpfc_drop_node(phba, ndlp); + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, + nlp_listp) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } return 0; @@ -723,9 +734,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) case LA_4GHZ_LINK: phba->fc_linkspeed = LA_4GHZ_LINK; break; - case LA_8GHZ_LINK: - phba->fc_linkspeed = LA_8GHZ_LINK; - break; default: phba->fc_linkspeed = LA_UNKNW_LINK; break; @@ -881,21 +889,12 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) if (la->attType == AT_LINK_UP) { phba->fc_stat.LinkUp++; - if (phba->fc_flag & FC_LOOPBACK_MODE) { - lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "%d:1306 Link Up Event in loop back mode " - "x%x received Data: x%x x%x x%x x%x\n", - phba->brd_no, la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, - phba->alpa_map[0]); - } else { - lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, + lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "%d:1303 Link Up Event x%x received " "Data: x%x x%x x%x x%x\n", phba->brd_no, la->eventTag, phba->fc_eventTag, la->granted_AL_PA, la->UlnkSpeed, phba->alpa_map[0]); - } lpfc_mbx_process_link_up(phba, la); } else { phba->fc_stat.LinkDown++; @@ -941,7 +940,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); - lpfc_nlp_put(ndlp); return; } @@ -968,14 +966,11 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ndlp = (struct lpfc_nodelist *) pmb->context2; mp = (struct lpfc_dmabuf *) (pmb->context1); - pmb->context1 = NULL; - pmb->context2 = NULL; - if (mb->mbxStatus) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - lpfc_nlp_put(ndlp); + mempool_free( pmb, phba->mbox_mem_pool); + mempool_free( ndlp, phba->nlp_mem_pool); /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(phba); @@ -985,11 +980,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) return; } + pmb->context1 = NULL; + ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_type |= NLP_FABRIC; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); - - lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */ + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); if (phba->hba_state == LPFC_FABRIC_CFG_LINK) { /* This NPort has been assigned an NPort_ID by the fabric as a @@ -1000,7 +996,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) */ lpfc_issue_els_scr(phba, SCR_DID, 0); - ndlp = lpfc_findnode_did(phba, NameServer_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); if (!ndlp) { /* Allocate a new node instance. If the pool is empty, * start the discovery process and skip the Nameserver @@ -1012,14 +1008,15 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_disc_start(phba); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + mempool_free( pmb, phba->mbox_mem_pool); return; } else { lpfc_nlp_init(phba, ndlp, NameServer_DID); ndlp->nlp_type |= NLP_FABRIC; } } - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, NameServer_DID, 0); if (phba->cfg_fdmi_on) { ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, @@ -1035,7 +1032,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + mempool_free( pmb, phba->mbox_mem_pool); return; } @@ -1060,11 +1057,10 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) mp = (struct lpfc_dmabuf *) (pmb->context1); if (mb->mbxStatus) { - lpfc_nlp_put(ndlp); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); - lpfc_drop_node(phba, ndlp); + mempool_free( pmb, phba->mbox_mem_pool); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); /* RegLogin failed, so just use loop map to make discovery list */ @@ -1079,7 +1075,8 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_type |= NLP_FABRIC; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); if (phba->hba_state < LPFC_HBA_READY) { /* Link up discovery requires Fabrib registration. */ @@ -1096,7 +1093,6 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_disc_start(phba); } - lpfc_nlp_put(ndlp); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free( pmb, phba->mbox_mem_pool); @@ -1105,7 +1101,8 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } static void -lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) +lpfc_register_remote_port(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp) { struct fc_rport *rport; struct lpfc_rport_data *rdata; @@ -1117,19 +1114,8 @@ lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) rport_ids.port_id = ndlp->nlp_DID; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - /* - * We leave our node pointer in rport->dd_data when we unregister a - * FCP target port. But fc_remote_port_add zeros the space to which - * rport->dd_data points. So, if we're reusing a previously - * registered port, drop the reference that we took the last time we - * registered the port. - */ - if (ndlp->rport && ndlp->rport->dd_data && - *(struct lpfc_rport_data **) ndlp->rport->dd_data) { - lpfc_nlp_put(ndlp); - } ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); - if (!rport || !get_device(&rport->dev)) { + if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, "Warning: fc_remote_port_add failed\n"); return; @@ -1139,7 +1125,7 @@ lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) rport->maxframe_size = ndlp->nlp_maxframe; rport->supported_classes = ndlp->nlp_class_sup; rdata = rport->dd_data; - rdata->pnode = lpfc_nlp_get(ndlp); + rdata->pnode = ndlp; if (ndlp->nlp_type & NLP_FCP_TARGET) rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; @@ -1159,7 +1145,8 @@ lpfc_register_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) } static void -lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) +lpfc_unregister_remote_port(struct lpfc_hba * phba, + struct lpfc_nodelist * ndlp) { struct fc_rport *rport = ndlp->rport; struct lpfc_rport_data *rdata = rport->dd_data; @@ -1167,8 +1154,6 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) if (rport->scsi_target_id == -1) { ndlp->rport = NULL; rdata->pnode = NULL; - lpfc_nlp_put(ndlp); - put_device(&rport->dev); } fc_remote_port_delete(rport); @@ -1176,70 +1161,178 @@ lpfc_unregister_remote_port(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) return; } -static void -lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count) +int +lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) { + enum { none, unmapped, mapped } rport_add = none, rport_del = none; + struct lpfc_sli *psli; + + psli = &phba->sli; + /* Sanity check to ensure we are not moving to / from the same list */ + if ((nlp->nlp_flag & NLP_LIST_MASK) == list) + if (list != NLP_NO_LIST) + return 0; + spin_lock_irq(phba->host->host_lock); - switch (state) { - case NLP_STE_UNUSED_NODE: - phba->fc_unused_cnt += count; + switch (nlp->nlp_flag & NLP_LIST_MASK) { + case NLP_NO_LIST: /* Not on any list */ break; - case NLP_STE_PLOGI_ISSUE: - phba->fc_plogi_cnt += count; + case NLP_UNUSED_LIST: + phba->fc_unused_cnt--; + list_del(&nlp->nlp_listp); break; - case NLP_STE_ADISC_ISSUE: - phba->fc_adisc_cnt += count; + case NLP_PLOGI_LIST: + phba->fc_plogi_cnt--; + list_del(&nlp->nlp_listp); break; - case NLP_STE_REG_LOGIN_ISSUE: - phba->fc_reglogin_cnt += count; + case NLP_ADISC_LIST: + phba->fc_adisc_cnt--; + list_del(&nlp->nlp_listp); break; - case NLP_STE_PRLI_ISSUE: - phba->fc_prli_cnt += count; + case NLP_REGLOGIN_LIST: + phba->fc_reglogin_cnt--; + list_del(&nlp->nlp_listp); break; - case NLP_STE_UNMAPPED_NODE: - phba->fc_unmap_cnt += count; + case NLP_PRLI_LIST: + phba->fc_prli_cnt--; + list_del(&nlp->nlp_listp); break; - case NLP_STE_MAPPED_NODE: - phba->fc_map_cnt += count; + case NLP_UNMAPPED_LIST: + phba->fc_unmap_cnt--; + list_del(&nlp->nlp_listp); + nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; + nlp->nlp_type &= ~NLP_FC_NODE; + phba->nport_event_cnt++; + if (nlp->rport) + rport_del = unmapped; break; - case NLP_STE_NPR_NODE: - phba->fc_npr_cnt += count; + case NLP_MAPPED_LIST: + phba->fc_map_cnt--; + list_del(&nlp->nlp_listp); + phba->nport_event_cnt++; + if (nlp->rport) + rport_del = mapped; + break; + case NLP_NPR_LIST: + phba->fc_npr_cnt--; + list_del(&nlp->nlp_listp); + /* Stop delay tmo if taking node off NPR list */ + if ((nlp->nlp_flag & NLP_DELAY_TMO) && + (list != NLP_NPR_LIST)) { + spin_unlock_irq(phba->host->host_lock); + lpfc_cancel_retry_delay_tmo(phba, nlp); + spin_lock_irq(phba->host->host_lock); + } break; } - spin_unlock_irq(phba->host->host_lock); -} -static void -lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, - int old_state, int new_state) -{ - if (new_state == NLP_STE_UNMAPPED_NODE) { - ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); - ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; - ndlp->nlp_type |= NLP_FC_NODE; - } - if (new_state == NLP_STE_MAPPED_NODE) - ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; - if (new_state == NLP_STE_NPR_NODE) - ndlp->nlp_flag &= ~NLP_RCV_PLOGI; - - /* Transport interface */ - if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE || - old_state == NLP_STE_UNMAPPED_NODE)) { + nlp->nlp_flag &= ~NLP_LIST_MASK; + + /* Add NPort to list */ + lpfc_printf_log(phba, + KERN_INFO, + LOG_NODE, + "%d:0904 Add NPort x%x to %d list Data: x%x\n", + phba->brd_no, + nlp->nlp_DID, list, nlp->nlp_flag); + + switch (list) { + case NLP_NO_LIST: /* No list, just remove it */ + spin_unlock_irq(phba->host->host_lock); + lpfc_nlp_remove(phba, nlp); + spin_lock_irq(phba->host->host_lock); + /* as node removed - stop further transport calls */ + rport_del = none; + break; + case NLP_UNUSED_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the unused list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list); + phba->fc_unused_cnt++; + break; + case NLP_PLOGI_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the plogi list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list); + phba->fc_plogi_cnt++; + break; + case NLP_ADISC_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the adisc list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list); + phba->fc_adisc_cnt++; + break; + case NLP_REGLOGIN_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the reglogin list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list); + phba->fc_reglogin_cnt++; + break; + case NLP_PRLI_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the prli list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list); + phba->fc_prli_cnt++; + break; + case NLP_UNMAPPED_LIST: + rport_add = unmapped; + /* ensure all vestiges of "mapped" significance are gone */ + nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); + nlp->nlp_flag |= list; + /* Put it at the end of the unmap list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); + phba->fc_unmap_cnt++; phba->nport_event_cnt++; - lpfc_unregister_remote_port(phba, ndlp); + nlp->nlp_flag &= ~NLP_NODEV_REMOVE; + nlp->nlp_type |= NLP_FC_NODE; + break; + case NLP_MAPPED_LIST: + rport_add = mapped; + nlp->nlp_flag |= list; + /* Put it at the end of the map list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); + phba->fc_map_cnt++; + phba->nport_event_cnt++; + nlp->nlp_flag &= ~NLP_NODEV_REMOVE; + break; + case NLP_NPR_LIST: + nlp->nlp_flag |= list; + /* Put it at the end of the npr list */ + list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); + phba->fc_npr_cnt++; + + nlp->nlp_flag &= ~NLP_RCV_PLOGI; + break; + case NLP_JUST_DQ: + break; } - if (new_state == NLP_STE_MAPPED_NODE || - new_state == NLP_STE_UNMAPPED_NODE) { - phba->nport_event_cnt++; + spin_unlock_irq(phba->host->host_lock); + + /* + * We make all the calls into the transport after we have + * moved the node between lists. This so that we don't + * release the lock while in-between lists. + */ + + /* Don't upcall midlayer if we're unloading */ + if (!(phba->fc_flag & FC_UNLOADING)) { + /* + * We revalidate the rport pointer as the "add" function + * may have removed the remote port. + */ + if ((rport_del != none) && nlp->rport) + lpfc_unregister_remote_port(phba, nlp); + + if (rport_add != none) { /* * Tell the fc transport about the port, if we haven't * already. If we have, and it's a scsi entity, be * sure to unblock any attached scsi devices */ - lpfc_register_remote_port(phba, ndlp); - } + if ((!nlp->rport) || (nlp->rport->port_state == + FC_PORTSTATE_BLOCKED)) + lpfc_register_remote_port(phba, nlp); /* * if we added to Mapped list, but the remote port @@ -1247,95 +1340,19 @@ lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, * our presentable range - move the node to the * Unmapped List */ - if (new_state == NLP_STE_MAPPED_NODE && - (!ndlp->rport || - ndlp->rport->scsi_target_id == -1 || - ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) { - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag |= NLP_TGT_NO_SCSIID; - spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); - } -} - -static char * -lpfc_nlp_state_name(char *buffer, size_t size, int state) -{ - static char *states[] = { - [NLP_STE_UNUSED_NODE] = "UNUSED", - [NLP_STE_PLOGI_ISSUE] = "PLOGI", - [NLP_STE_ADISC_ISSUE] = "ADISC", - [NLP_STE_REG_LOGIN_ISSUE] = "REGLOGIN", - [NLP_STE_PRLI_ISSUE] = "PRLI", - [NLP_STE_UNMAPPED_NODE] = "UNMAPPED", - [NLP_STE_MAPPED_NODE] = "MAPPED", - [NLP_STE_NPR_NODE] = "NPR", - }; - - if (state < ARRAY_SIZE(states) && states[state]) - strlcpy(buffer, states[state], size); - else - snprintf(buffer, size, "unknown (%d)", state); - return buffer; -} - -void -lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state) -{ - int old_state = ndlp->nlp_state; - char name1[16], name2[16]; - - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0904 NPort state transition x%06x, %s -> %s\n", - phba->brd_no, - ndlp->nlp_DID, - lpfc_nlp_state_name(name1, sizeof(name1), old_state), - lpfc_nlp_state_name(name2, sizeof(name2), state)); - if (old_state == NLP_STE_NPR_NODE && - (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && - state != NLP_STE_NPR_NODE) - lpfc_cancel_retry_delay_tmo(phba, ndlp); - if (old_state == NLP_STE_UNMAPPED_NODE) { - ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID; - ndlp->nlp_type &= ~NLP_FC_NODE; + if ((rport_add == mapped) && + ((!nlp->rport) || + (nlp->rport->scsi_target_id == -1) || + (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) { + nlp->nlp_state = NLP_STE_UNMAPPED_NODE; + spin_lock_irq(phba->host->host_lock); + nlp->nlp_flag |= NLP_TGT_NO_SCSIID; + spin_unlock_irq(phba->host->host_lock); + lpfc_nlp_list(phba, nlp, NLP_UNMAPPED_LIST); + } + } } - - if (list_empty(&ndlp->nlp_listp)) { - spin_lock_irq(phba->host->host_lock); - list_add_tail(&ndlp->nlp_listp, &phba->fc_nodes); - spin_unlock_irq(phba->host->host_lock); - } else if (old_state) - lpfc_nlp_counters(phba, old_state, -1); - - ndlp->nlp_state = state; - lpfc_nlp_counters(phba, state, 1); - lpfc_nlp_state_cleanup(phba, ndlp, old_state, state); -} - -void -lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) -{ - if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) - lpfc_cancel_retry_delay_tmo(phba, ndlp); - if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) - lpfc_nlp_counters(phba, ndlp->nlp_state, -1); - spin_lock_irq(phba->host->host_lock); - list_del_init(&ndlp->nlp_listp); - spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0); -} - -void -lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) -{ - if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) - lpfc_cancel_retry_delay_tmo(phba, ndlp); - if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) - lpfc_nlp_counters(phba, ndlp->nlp_state, -1); - spin_lock_irq(phba->host->host_lock); - list_del_init(&ndlp->nlp_listp); - spin_unlock_irq(phba->host->host_lock); - lpfc_nlp_put(ndlp); + return 0; } /* @@ -1447,7 +1464,6 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, static int lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) { - LIST_HEAD(completions); struct lpfc_sli *psli; struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; @@ -1476,29 +1492,29 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) (phba, pring, iocb, ndlp))) { /* It matches, so deque and call compl with an error */ - list_move_tail(&iocb->list, - &completions); + list_del(&iocb->list); pring->txq_cnt--; + if (iocb->iocb_cmpl) { + icmd = &iocb->iocb; + icmd->ulpStatus = + IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = + IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host-> + host_lock); + (iocb->iocb_cmpl) (phba, + iocb, iocb); + spin_lock_irq(phba->host-> + host_lock); + } else + lpfc_sli_release_iocbq(phba, + iocb); } } spin_unlock_irq(phba->host->host_lock); } } - - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del(&iocb->list); - - if (iocb->iocb_cmpl) { - icmd = &iocb->iocb; - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } else - lpfc_sli_release_iocbq(phba, iocb); - } - return 0; } @@ -1538,7 +1554,7 @@ lpfc_unreg_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) * so it can be freed. */ static int -lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) +lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) { LPFC_MBOXQ_t *mb; LPFC_MBOXQ_t *nextmb; @@ -1551,7 +1567,17 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - lpfc_dequeue_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ); + + /* + * if unloading the driver - just leave the remote port in place. + * The driver unload will force the attached devices to detach + * and flush cache's w/o generating flush errors. + */ + if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { + lpfc_unregister_remote_port(phba, ndlp); + ndlp->nlp_sid = NLP_NO_SID; + } /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ if ((mb = phba->sli.mbox_active)) { @@ -1573,12 +1599,11 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) } list_del(&mb->list); mempool_free(mb, phba->mbox_mem_pool); - lpfc_nlp_put(ndlp); } } spin_unlock_irq(phba->host->host_lock); - lpfc_els_abort(phba,ndlp); + lpfc_els_abort(phba,ndlp,0); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~NLP_DELAY_TMO; spin_unlock_irq(phba->host->host_lock); @@ -1599,27 +1624,27 @@ lpfc_cleanup_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) * If we are in the middle of using the nlp in the discovery state * machine, defer the free till we reach the end of the state machine. */ -static void -lpfc_nlp_remove(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) +int +lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) { - struct lpfc_rport_data *rdata; if (ndlp->nlp_flag & NLP_DELAY_TMO) { lpfc_cancel_retry_delay_tmo(phba, ndlp); } - lpfc_cleanup_node(phba, ndlp); - - if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { - put_device(&ndlp->rport->dev); - rdata = ndlp->rport->dd_data; - rdata->pnode = NULL; - ndlp->rport = NULL; + if (ndlp->nlp_disc_refcnt) { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag |= NLP_DELAY_REMOVE; + spin_unlock_irq(phba->host->host_lock); + } else { + lpfc_freenode(phba, ndlp); + mempool_free( ndlp, phba->nlp_mem_pool); } + return 0; } static int -lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) +lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) { D_ID mydid; D_ID ndlpdid; @@ -1668,36 +1693,57 @@ lpfc_matchdid(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) return 0; } -/* Search for a nodelist entry */ +/* Search for a nodelist entry on a specific list */ struct lpfc_nodelist * -lpfc_findnode_did(struct lpfc_hba *phba, uint32_t did) +lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) { struct lpfc_nodelist *ndlp; + struct list_head *lists[]={&phba->fc_nlpunmap_list, + &phba->fc_nlpmap_list, + &phba->fc_plogi_list, + &phba->fc_adisc_list, + &phba->fc_reglogin_list, + &phba->fc_prli_list, + &phba->fc_npr_list, + &phba->fc_unused_list}; + uint32_t search[]={NLP_SEARCH_UNMAPPED, + NLP_SEARCH_MAPPED, + NLP_SEARCH_PLOGI, + NLP_SEARCH_ADISC, + NLP_SEARCH_REGLOGIN, + NLP_SEARCH_PRLI, + NLP_SEARCH_NPR, + NLP_SEARCH_UNUSED}; + int i; uint32_t data1; spin_lock_irq(phba->host->host_lock); - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0929 FIND node DID " - " Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; + for (i = 0; i < ARRAY_SIZE(lists); i++ ) { + if (!(order & search[i])) + continue; + list_for_each_entry(ndlp, lists[i], nlp_listp) { + if (lpfc_matchdid(phba, ndlp, did)) { + data1 = (((uint32_t) ndlp->nlp_state << 24) | + ((uint32_t) ndlp->nlp_xri << 16) | + ((uint32_t) ndlp->nlp_type << 8) | + ((uint32_t) ndlp->nlp_rpi & 0xff)); + lpfc_printf_log(phba, KERN_INFO, LOG_NODE, + "%d:0929 FIND node DID " + " Data: x%p x%x x%x x%x\n", + phba->brd_no, + ndlp, ndlp->nlp_DID, + ndlp->nlp_flag, data1); + spin_unlock_irq(phba->host->host_lock); + return ndlp; + } } } spin_unlock_irq(phba->host->host_lock); /* FIND node did NOT FOUND */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0932 FIND node did x%x NOT FOUND.\n", - phba->brd_no, did); + "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", + phba->brd_no, did, order); return NULL; } @@ -1705,8 +1751,9 @@ struct lpfc_nodelist * lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) { struct lpfc_nodelist *ndlp; + uint32_t flg; - ndlp = lpfc_findnode_did(phba, did); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did); if (!ndlp) { if ((phba->fc_flag & FC_RSCN_MODE) && ((lpfc_rscn_payload_check(phba, did) == 0))) @@ -1716,7 +1763,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) if (!ndlp) return NULL; lpfc_nlp_init(phba, ndlp, did); - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; return ndlp; } @@ -1732,10 +1780,11 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did) } else ndlp = NULL; } else { - if (ndlp->nlp_state == NLP_STE_ADISC_ISSUE || - ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) + flg = ndlp->nlp_flag & NLP_LIST_MASK; + if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST)) return NULL; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag |= NLP_NPR_2B_DISC; } return ndlp; @@ -1793,9 +1842,8 @@ lpfc_disc_start(struct lpfc_hba * phba) struct lpfc_sli *psli; LPFC_MBOXQ_t *mbox; struct lpfc_nodelist *ndlp, *next_ndlp; - uint32_t num_sent; + uint32_t did_changed, num_sent; uint32_t clear_la_pending; - int did_changed; int rc; psli = &phba->sli; @@ -1829,13 +1877,14 @@ lpfc_disc_start(struct lpfc_hba * phba) phba->fc_plogi_cnt, phba->fc_adisc_cnt); /* If our did changed, we MUST do PLOGI */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_NPR_NODE && - (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && - did_changed) { - spin_lock_irq(phba->host->host_lock); - ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(phba->host->host_lock); + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { + if (did_changed) { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + spin_unlock_irq(phba->host->host_lock); + } } } @@ -1895,11 +1944,11 @@ lpfc_disc_start(struct lpfc_hba * phba) static void lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) { - LIST_HEAD(completions); struct lpfc_sli *psli; IOCB_t *icmd; struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_sli_ring *pring; + struct lpfc_dmabuf *mp; psli = &phba->sli; pring = &psli->ring[LPFC_ELS_RING]; @@ -1907,7 +1956,6 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) /* Error matching iocb on txq or txcmplq * First check the txq. */ - spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { if (iocb->context1 != ndlp) { continue; @@ -1916,8 +1964,9 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { - list_move_tail(&iocb->list, &completions); + list_del(&iocb->list); pring->txq_cnt--; + lpfc_els_free_iocb(phba, iocb); } } @@ -1929,22 +1978,43 @@ lpfc_free_tx(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) icmd = &iocb->iocb; if ((icmd->ulpCommand == CMD_ELS_REQUEST64_CR) || (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { - lpfc_sli_issue_abort_iotag(phba, pring, iocb); - } - } - spin_unlock_irq(phba->host->host_lock); - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del(&iocb->list); + iocb->iocb_cmpl = NULL; + /* context2 = cmd, context2->next = rsp, context3 = + bpl */ + if (iocb->context2) { + /* Free the response IOCB before handling the + command. */ + + mp = (struct lpfc_dmabuf *) (iocb->context2); + mp = list_get_first(&mp->list, + struct lpfc_dmabuf, + list); + if (mp) { + /* Delay before releasing rsp buffer to + * give UNREG mbox a chance to take + * effect. + */ + list_add(&mp->list, + &phba->freebufList); + } + lpfc_mbuf_free(phba, + ((struct lpfc_dmabuf *) + iocb->context2)->virt, + ((struct lpfc_dmabuf *) + iocb->context2)->phys); + kfree(iocb->context2); + } - if (iocb->iocb_cmpl) { - icmd = &iocb->iocb; - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } else - lpfc_sli_release_iocbq(phba, iocb); + if (iocb->context3) { + lpfc_mbuf_free(phba, + ((struct lpfc_dmabuf *) + iocb->context3)->virt, + ((struct lpfc_dmabuf *) + iocb->context3)->phys); + kfree(iocb->context3); + } + } } return; @@ -1955,16 +2025,21 @@ lpfc_disc_flush_list(struct lpfc_hba * phba) { struct lpfc_nodelist *ndlp, *next_ndlp; - if (phba->fc_plogi_cnt || phba->fc_adisc_cnt) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, - nlp_listp) { - if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || - ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { - lpfc_free_tx(phba, ndlp); - lpfc_nlp_put(ndlp); - } + if (phba->fc_plogi_cnt) { + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, + nlp_listp) { + lpfc_free_tx(phba, ndlp); + lpfc_nlp_remove(phba, ndlp); + } + } + if (phba->fc_adisc_cnt) { + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, + nlp_listp) { + lpfc_free_tx(phba, ndlp); + lpfc_nlp_remove(phba, ndlp); } } + return; } /*****************************************************************************/ @@ -2033,13 +2108,11 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) phba->brd_no); /* Start discovery by sending FLOGI, clean up old rpis */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, - nlp_listp) { - if (ndlp->nlp_state != NLP_STE_NPR_NODE) - continue; + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { if (ndlp->nlp_type & NLP_FABRIC) { /* Clean up the ndlp on Fabric connections */ - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { /* Fail outstanding IO now since device * is marked for PLOGI. @@ -2080,9 +2153,9 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) "login\n", phba->brd_no); /* Next look for NameServer ndlp */ - ndlp = lpfc_findnode_did(phba, NameServer_DID); + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID); if (ndlp) - lpfc_nlp_put(ndlp); + lpfc_nlp_remove(phba, ndlp); /* Start discovery */ lpfc_disc_start(phba); break; @@ -2095,8 +2168,9 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) phba->brd_no, phba->fc_ns_retry, LPFC_MAX_NS_RETRY); - ndlp = lpfc_findnode_did(phba, NameServer_DID); - if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { + ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, + NameServer_DID); + if (ndlp) { if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) { /* Try it one more time */ rc = lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT); @@ -2146,7 +2220,6 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0; rc = lpfc_sli_issue_mbox(phba, initlinkmbox, (MBX_NOWAIT | MBX_STOP_IOCB)); - lpfc_set_loopback_flag(phba); if (rc == MBX_NOT_FINISHED) mempool_free(initlinkmbox, phba->mbox_mem_pool); @@ -2244,7 +2317,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ndlp->nlp_rpi = mb->un.varWords[0]; ndlp->nlp_type |= NLP_FABRIC; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); /* Start issuing Fabric-Device Management Interface (FDMI) * command to 0xfffffa (FDMI well known port) @@ -2259,100 +2333,87 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) mod_timer(&phba->fc_fdmitmo, jiffies + HZ * 60); } - /* Mailbox took a reference to the node */ - lpfc_nlp_put(ndlp); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - mempool_free(pmb, phba->mbox_mem_pool); + mempool_free( pmb, phba->mbox_mem_pool); return; } -static int -lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param) -{ - uint16_t *rpi = param; - - return ndlp->nlp_rpi == *rpi; -} - -static int -lpfc_filter_by_wwpn(struct lpfc_nodelist *ndlp, void *param) -{ - return memcmp(&ndlp->nlp_portname, param, - sizeof(ndlp->nlp_portname)) == 0; -} - -/* - * Search node lists for a remote port matching filter criteria - * Caller needs to hold host_lock before calling this routine. - */ -struct lpfc_nodelist * -__lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) -{ - struct lpfc_nodelist *ndlp; - - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state != NLP_STE_UNUSED_NODE && - filter(ndlp, param)) - return ndlp; - } - return NULL; -} - /* - * Search node lists for a remote port matching filter criteria - * This routine is used when the caller does NOT have host_lock. + * This routine looks up the ndlp lists + * for the given RPI. If rpi found + * it return the node list pointer + * else return NULL. */ -struct lpfc_nodelist * -lpfc_find_node(struct lpfc_hba *phba, node_filter filter, void *param) -{ - struct lpfc_nodelist *ndlp; - - spin_lock_irq(phba->host->host_lock); - ndlp = __lpfc_find_node(phba, filter, param); - spin_unlock_irq(phba->host->host_lock); - return ndlp; -} - -/* - * This routine looks up the ndlp lists for the given RPI. If rpi found it - * returns the node list pointer else return NULL. - */ -struct lpfc_nodelist * -__lpfc_findnode_rpi(struct lpfc_hba *phba, uint16_t rpi) -{ - return __lpfc_find_node(phba, lpfc_filter_by_rpi, &rpi); -} - struct lpfc_nodelist * lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi) { struct lpfc_nodelist *ndlp; + struct list_head * lists[]={&phba->fc_nlpunmap_list, + &phba->fc_nlpmap_list, + &phba->fc_plogi_list, + &phba->fc_adisc_list, + &phba->fc_reglogin_list}; + int i; spin_lock_irq(phba->host->host_lock); - ndlp = __lpfc_findnode_rpi(phba, rpi); + for (i = 0; i < ARRAY_SIZE(lists); i++ ) + list_for_each_entry(ndlp, lists[i], nlp_listp) + if (ndlp->nlp_rpi == rpi) { + spin_unlock_irq(phba->host->host_lock); + return ndlp; + } spin_unlock_irq(phba->host->host_lock); - return ndlp; + return NULL; } /* - * This routine looks up the ndlp lists for the given WWPN. If WWPN found it - * returns the node list pointer else return NULL. + * This routine looks up the ndlp lists + * for the given WWPN. If WWPN found + * it return the node list pointer + * else return NULL. */ struct lpfc_nodelist * -lpfc_findnode_wwpn(struct lpfc_hba *phba, struct lpfc_name *wwpn) +lpfc_findnode_wwpn(struct lpfc_hba * phba, uint32_t order, + struct lpfc_name * wwpn) { struct lpfc_nodelist *ndlp; + struct list_head * lists[]={&phba->fc_nlpunmap_list, + &phba->fc_nlpmap_list, + &phba->fc_npr_list, + &phba->fc_plogi_list, + &phba->fc_adisc_list, + &phba->fc_reglogin_list, + &phba->fc_prli_list}; + uint32_t search[]={NLP_SEARCH_UNMAPPED, + NLP_SEARCH_MAPPED, + NLP_SEARCH_NPR, + NLP_SEARCH_PLOGI, + NLP_SEARCH_ADISC, + NLP_SEARCH_REGLOGIN, + NLP_SEARCH_PRLI}; + int i; spin_lock_irq(phba->host->host_lock); - ndlp = __lpfc_find_node(phba, lpfc_filter_by_wwpn, wwpn); + for (i = 0; i < ARRAY_SIZE(lists); i++ ) { + if (!(order & search[i])) + continue; + list_for_each_entry(ndlp, lists[i], nlp_listp) { + if (memcmp(&ndlp->nlp_portname, wwpn, + sizeof(struct lpfc_name)) == 0) { + spin_unlock_irq(phba->host->host_lock); + return ndlp; + } + } + } spin_unlock_irq(phba->host->host_lock); return NULL; } void -lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) +lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, + uint32_t did) { memset(ndlp, 0, sizeof (struct lpfc_nodelist)); INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); @@ -2362,30 +2423,5 @@ lpfc_nlp_init(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint32_t did) ndlp->nlp_DID = did; ndlp->nlp_phba = phba; ndlp->nlp_sid = NLP_NO_SID; - INIT_LIST_HEAD(&ndlp->nlp_listp); - kref_init(&ndlp->kref); return; } - -void -lpfc_nlp_release(struct kref *kref) -{ - struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, - kref); - lpfc_nlp_remove(ndlp->nlp_phba, ndlp); - mempool_free(ndlp, ndlp->nlp_phba->nlp_mem_pool); -} - -struct lpfc_nodelist * -lpfc_nlp_get(struct lpfc_nodelist *ndlp) -{ - if (ndlp) - kref_get(&ndlp->kref); - return ndlp; -} - -int -lpfc_nlp_put(struct lpfc_nodelist *ndlp) -{ - return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; -} diff --git a/trunk/drivers/scsi/lpfc/lpfc_hw.h b/trunk/drivers/scsi/lpfc/lpfc_hw.h index 2623a9bc7775..f79cb6136906 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_hw.h +++ b/trunk/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -1078,8 +1078,6 @@ typedef struct { /* Start FireFly Register definitions */ #define PCI_VENDOR_ID_EMULEX 0x10df #define PCI_DEVICE_ID_FIREFLY 0x1ae5 -#define PCI_DEVICE_ID_SAT_SMB 0xf011 -#define PCI_DEVICE_ID_SAT_MID 0xf015 #define PCI_DEVICE_ID_RFLY 0xf095 #define PCI_DEVICE_ID_PFLY 0xf098 #define PCI_DEVICE_ID_LP101 0xf0a1 @@ -1091,9 +1089,6 @@ typedef struct { #define PCI_DEVICE_ID_NEPTUNE 0xf0f5 #define PCI_DEVICE_ID_NEPTUNE_SCSP 0xf0f6 #define PCI_DEVICE_ID_NEPTUNE_DCSP 0xf0f7 -#define PCI_DEVICE_ID_SAT 0xf100 -#define PCI_DEVICE_ID_SAT_SCSP 0xf111 -#define PCI_DEVICE_ID_SAT_DCSP 0xf112 #define PCI_DEVICE_ID_SUPERFLY 0xf700 #define PCI_DEVICE_ID_DRAGONFLY 0xf800 #define PCI_DEVICE_ID_CENTAUR 0xf900 @@ -1103,7 +1098,6 @@ typedef struct { #define PCI_DEVICE_ID_LP10000S 0xfc00 #define PCI_DEVICE_ID_LP11000S 0xfc10 #define PCI_DEVICE_ID_LPE11000S 0xfc20 -#define PCI_DEVICE_ID_SAT_S 0xfc40 #define PCI_DEVICE_ID_HELIOS 0xfd00 #define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11 #define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12 @@ -1124,7 +1118,6 @@ typedef struct { #define HELIOS_JEDEC_ID 0x0364 #define ZEPHYR_JEDEC_ID 0x0577 #define VIPER_JEDEC_ID 0x4838 -#define SATURN_JEDEC_ID 0x1004 #define JEDEC_ID_MASK 0x0FFFF000 #define JEDEC_ID_SHIFT 12 @@ -1572,7 +1565,7 @@ typedef struct { #define LINK_SPEED_1G 1 /* 1 Gigabaud */ #define LINK_SPEED_2G 2 /* 2 Gigabaud */ #define LINK_SPEED_4G 4 /* 4 Gigabaud */ -#define LINK_SPEED_8G 8 /* 8 Gigabaud */ +#define LINK_SPEED_8G 8 /* 4 Gigabaud */ #define LINK_SPEED_10G 16 /* 10 Gigabaud */ } INIT_LINK_VAR; diff --git a/trunk/drivers/scsi/lpfc/lpfc_init.c b/trunk/drivers/scsi/lpfc/lpfc_init.c index dcb4ba0ecee1..dcf6106f557a 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_init.c +++ b/trunk/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -386,12 +386,12 @@ lpfc_config_port_post(struct lpfc_hba * phba) * Setup the ring 0 (els) timeout handler */ timeout = phba->fc_ratov << 1; - mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout); + phba->els_tmofunc.expires = jiffies + HZ * timeout; + add_timer(&phba->els_tmofunc); lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - lpfc_set_loopback_flag(phba); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, @@ -418,6 +418,33 @@ lpfc_config_port_post(struct lpfc_hba * phba) return (0); } +static int +lpfc_discovery_wait(struct lpfc_hba *phba) +{ + int i = 0; + + while ((phba->hba_state != LPFC_HBA_READY) || + (phba->num_disc_nodes) || (phba->fc_prli_sent) || + ((phba->fc_map_cnt == 0) && (i<2)) || + (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) { + /* Check every second for 30 retries. */ + i++; + if (i > 30) { + return -ETIMEDOUT; + } + if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) { + /* The link is down. Set linkdown timeout */ + return -ETIMEDOUT; + } + + /* Delay for 1 second to give discovery time to complete. */ + msleep(1000); + + } + + return 0; +} + /************************************************************************/ /* */ /* lpfc_hba_down_prep */ @@ -523,15 +550,12 @@ lpfc_handle_eratt(struct lpfc_hba * phba) * There was a firmware error. Take the hba offline and then * attempt to restart it. */ - lpfc_offline_prep(phba); lpfc_offline(phba); lpfc_sli_brdrestart(phba); if (lpfc_online(phba) == 0) { /* Initialize the HBA */ mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); - lpfc_unblock_mgmt_io(phba); return; } - lpfc_unblock_mgmt_io(phba); } else { /* The if clause above forces this code path when the status * failure is a value other than FFER6. Do not call the offline @@ -549,9 +573,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba) SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; - lpfc_offline_prep(phba); lpfc_offline(phba); - lpfc_unblock_mgmt_io(phba); phba->hba_state = LPFC_HBA_ERROR; lpfc_hba_down_post(phba); } @@ -611,7 +633,7 @@ lpfc_handle_latt(struct lpfc_hba * phba) lpfc_handle_latt_free_mp: kfree(mp); lpfc_handle_latt_free_pmb: - mempool_free(pmb, phba->mbox_mem_pool); + kfree(pmb); lpfc_handle_latt_err_exit: /* Enable Link attention interrupts */ spin_lock_irq(phba->host->host_lock); @@ -903,24 +925,6 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) m = (typeof(m)){"LPe11000-S", max_speed, "PCIe"}; break; - case PCI_DEVICE_ID_SAT: - m = (typeof(m)){"LPe12000", max_speed, "PCIe"}; - break; - case PCI_DEVICE_ID_SAT_MID: - m = (typeof(m)){"LPe1250", max_speed, "PCIe"}; - break; - case PCI_DEVICE_ID_SAT_SMB: - m = (typeof(m)){"LPe121", max_speed, "PCIe"}; - break; - case PCI_DEVICE_ID_SAT_DCSP: - m = (typeof(m)){"LPe12002-SP", max_speed, "PCIe"}; - break; - case PCI_DEVICE_ID_SAT_SCSP: - m = (typeof(m)){"LPe12000-SP", max_speed, "PCIe"}; - break; - case PCI_DEVICE_ID_SAT_S: - m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"}; - break; default: m = (typeof(m)){ NULL }; break; @@ -1170,17 +1174,69 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) } static void -lpfc_cleanup(struct lpfc_hba * phba) +lpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind) { struct lpfc_nodelist *ndlp, *next_ndlp; /* clean up phba - lpfc specific */ lpfc_can_disctmo(phba); - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) - lpfc_nlp_put(ndlp); + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } - INIT_LIST_HEAD(&phba->fc_nodes); + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, + nlp_listp) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + } + + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + lpfc_nlp_remove(phba, ndlp); + } + + INIT_LIST_HEAD(&phba->fc_nlpmap_list); + INIT_LIST_HEAD(&phba->fc_nlpunmap_list); + INIT_LIST_HEAD(&phba->fc_unused_list); + INIT_LIST_HEAD(&phba->fc_plogi_list); + INIT_LIST_HEAD(&phba->fc_adisc_list); + INIT_LIST_HEAD(&phba->fc_reglogin_list); + INIT_LIST_HEAD(&phba->fc_prli_list); + INIT_LIST_HEAD(&phba->fc_npr_list); + + phba->fc_map_cnt = 0; + phba->fc_unmap_cnt = 0; + phba->fc_plogi_cnt = 0; + phba->fc_adisc_cnt = 0; + phba->fc_reglogin_cnt = 0; + phba->fc_prli_cnt = 0; + phba->fc_npr_cnt = 0; + phba->fc_unused_cnt= 0; return; } @@ -1206,6 +1262,21 @@ lpfc_stop_timer(struct lpfc_hba * phba) { struct lpfc_sli *psli = &phba->sli; + /* Instead of a timer, this has been converted to a + * deferred procedding list. + */ + while (!list_empty(&phba->freebufList)) { + + struct lpfc_dmabuf *mp = NULL; + + list_remove_head((&phba->freebufList), mp, + struct lpfc_dmabuf, list); + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + } + del_timer_sync(&phba->fcp_poll_timer); del_timer_sync(&phba->fc_estabtmo); del_timer_sync(&phba->fc_disctmo); @@ -1231,76 +1302,60 @@ lpfc_online(struct lpfc_hba * phba) "%d:0458 Bring Adapter online\n", phba->brd_no); - lpfc_block_mgmt_io(phba); - - if (!lpfc_sli_queue_setup(phba)) { - lpfc_unblock_mgmt_io(phba); + if (!lpfc_sli_queue_setup(phba)) return 1; - } - if (lpfc_sli_hba_setup(phba)) { /* Initialize the HBA */ - lpfc_unblock_mgmt_io(phba); + if (lpfc_sli_hba_setup(phba)) /* Initialize the HBA */ return 1; - } spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_OFFLINE_MODE; spin_unlock_irq(phba->host->host_lock); - lpfc_unblock_mgmt_io(phba); return 0; } -void -lpfc_block_mgmt_io(struct lpfc_hba * phba) -{ - unsigned long iflag; - - spin_lock_irqsave(phba->host->host_lock, iflag); - phba->fc_flag |= FC_BLOCK_MGMT_IO; - spin_unlock_irqrestore(phba->host->host_lock, iflag); -} - -void -lpfc_unblock_mgmt_io(struct lpfc_hba * phba) +int +lpfc_offline(struct lpfc_hba * phba) { + struct lpfc_sli_ring *pring; + struct lpfc_sli *psli; unsigned long iflag; + int i; + int cnt = 0; - spin_lock_irqsave(phba->host->host_lock, iflag); - phba->fc_flag &= ~FC_BLOCK_MGMT_IO; - spin_unlock_irqrestore(phba->host->host_lock, iflag); -} - -void -lpfc_offline_prep(struct lpfc_hba * phba) -{ - struct lpfc_nodelist *ndlp, *next_ndlp; + if (!phba) + return 0; if (phba->fc_flag & FC_OFFLINE_MODE) - return; + return 0; - lpfc_block_mgmt_io(phba); + psli = &phba->sli; lpfc_linkdown(phba); - - /* Issue an unreg_login to all nodes */ - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) - if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) - lpfc_unreg_rpi(phba, ndlp); - lpfc_sli_flush_mbox_queue(phba); -} -void -lpfc_offline(struct lpfc_hba * phba) -{ - unsigned long iflag; + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; + /* The linkdown event takes 30 seconds to timeout. */ + while (pring->txcmplq_cnt) { + mdelay(10); + if (cnt++ > 3000) { + lpfc_printf_log(phba, + KERN_WARNING, LOG_INIT, + "%d:0466 Outstanding IO when " + "bringing Adapter offline\n", + phba->brd_no); + break; + } + } + } - if (phba->fc_flag & FC_OFFLINE_MODE) - return; /* 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, @@ -1311,12 +1366,11 @@ lpfc_offline(struct lpfc_hba * phba) /* Bring down the SLI Layer and cleanup. The HBA is offline now. */ lpfc_sli_hba_down(phba); - lpfc_cleanup(phba); + lpfc_cleanup(phba, 1); spin_lock_irqsave(phba->host->host_lock, iflag); - phba->work_hba_events = 0; - phba->work_ha = 0; phba->fc_flag |= FC_OFFLINE_MODE; spin_unlock_irqrestore(phba->host->host_lock, iflag); + return 0; } /****************************************************************************** @@ -1353,156 +1407,6 @@ lpfc_scsi_free(struct lpfc_hba * phba) return 0; } -void lpfc_remove_device(struct lpfc_hba *phba) -{ - unsigned long iflag; - - lpfc_free_sysfs_attr(phba); - - spin_lock_irqsave(phba->host->host_lock, iflag); - phba->fc_flag |= FC_UNLOADING; - - spin_unlock_irqrestore(phba->host->host_lock, iflag); - - fc_remove_host(phba->host); - scsi_remove_host(phba->host); - - kthread_stop(phba->worker_thread); - - /* - * Bring down the SLI Layer. This step disable all interrupts, - * clears the rings, discards all mailbox commands, and resets - * the HBA. - */ - lpfc_sli_hba_down(phba); - lpfc_sli_brdrestart(phba); - - /* Release the irq reservation */ - free_irq(phba->pcidev->irq, phba); - pci_disable_msi(phba->pcidev); - - lpfc_cleanup(phba); - lpfc_stop_timer(phba); - phba->work_hba_events = 0; - - /* - * Call scsi_free before mem_free since scsi bufs are released to their - * corresponding pools here. - */ - lpfc_scsi_free(phba); - lpfc_mem_free(phba); - - /* Free resources associated with SLI2 interface */ - dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE, - phba->slim2p, phba->slim2p_mapping); - - /* unmap adapter SLIM and Control Registers */ - iounmap(phba->ctrl_regs_memmap_p); - iounmap(phba->slim_memmap_p); - - pci_release_regions(phba->pcidev); - pci_disable_device(phba->pcidev); - - idr_remove(&lpfc_hba_index, phba->brd_no); - scsi_host_put(phba->host); -} - -void lpfc_scan_start(struct Scsi_Host *host) -{ - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; - - if (lpfc_alloc_sysfs_attr(phba)) - goto error; - - phba->MBslimaddr = phba->slim_memmap_p; - phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; - phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET; - phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; - phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; - - if (lpfc_sli_hba_setup(phba)) - goto error; - - /* - * 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; - return; - -error: - lpfc_remove_device(phba); -} - -int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) -{ - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; - - if (!phba->host) - return 1; - if (time >= 30 * HZ) - goto finished; - - if (phba->hba_state != LPFC_HBA_READY) - return 0; - if (phba->num_disc_nodes || phba->fc_prli_sent) - return 0; - if ((phba->fc_map_cnt == 0) && (time < 2 * HZ)) - return 0; - if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) - return 0; - if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ)) - return 0; - -finished: - if (phba->cfg_poll & DISABLE_FCP_RING_INT) { - spin_lock_irq(shost->host_lock); - lpfc_poll_start_timer(phba); - spin_unlock_irq(shost->host_lock); - } - - /* - * set fixed host attributes - * Must done after lpfc_sli_hba_setup() - */ - - fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn); - fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn); - fc_host_supported_classes(shost) = FC_COS_CLASS3; - - memset(fc_host_supported_fc4s(shost), 0, - sizeof(fc_host_supported_fc4s(shost))); - fc_host_supported_fc4s(shost)[2] = 1; - fc_host_supported_fc4s(shost)[7] = 1; - - lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost)); - - fc_host_supported_speeds(shost) = 0; - if (phba->lmt & LMT_10Gb) - fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT; - if (phba->lmt & LMT_4Gb) - fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT; - if (phba->lmt & LMT_2Gb) - fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT; - if (phba->lmt & LMT_1Gb) - fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT; - - fc_host_maxframe_size(shost) = - ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | - (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb); - - /* This value is also unchanging */ - memset(fc_host_active_fc4s(shost), 0, - sizeof(fc_host_active_fc4s(shost))); - fc_host_active_fc4s(shost)[2] = 1; - fc_host_active_fc4s(shost)[7] = 1; - - spin_lock_irq(shost->host_lock); - phba->fc_flag &= ~FC_LOADING; - spin_unlock_irq(shost->host_lock); - - return 1; -} static int __devinit lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) @@ -1541,6 +1445,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_put_host; host->unique_id = phba->brd_no; + INIT_LIST_HEAD(&phba->ctrspbuflist); + INIT_LIST_HEAD(&phba->rnidrspbuflist); + INIT_LIST_HEAD(&phba->freebufList); /* Initialize timers used by driver */ init_timer(&phba->fc_estabtmo); @@ -1575,7 +1482,16 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) host->max_lun = phba->cfg_max_luns; host->this_id = -1; - INIT_LIST_HEAD(&phba->fc_nodes); + /* Initialize all internally managed lists. */ + INIT_LIST_HEAD(&phba->fc_nlpmap_list); + INIT_LIST_HEAD(&phba->fc_nlpunmap_list); + INIT_LIST_HEAD(&phba->fc_unused_list); + INIT_LIST_HEAD(&phba->fc_plogi_list); + INIT_LIST_HEAD(&phba->fc_adisc_list); + INIT_LIST_HEAD(&phba->fc_reglogin_list); + INIT_LIST_HEAD(&phba->fc_prli_list); + INIT_LIST_HEAD(&phba->fc_npr_list); + pci_set_master(pdev); retval = pci_set_mwi(pdev); @@ -1693,6 +1609,13 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) host->transportt = lpfc_transport_template; pci_set_drvdata(pdev, host); + error = scsi_add_host(host, &pdev->dev); + if (error) + goto out_kthread_stop; + + error = lpfc_alloc_sysfs_attr(phba); + if (error) + goto out_remove_host; if (phba->cfg_use_msi) { error = pci_enable_msi(phba->pcidev); @@ -1708,15 +1631,73 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0451 Enable interrupt handler failed\n", phba->brd_no); - goto out_kthread_stop; + goto out_free_sysfs_attr; } + phba->MBslimaddr = phba->slim_memmap_p; + phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; + phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET; + phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; + phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; - error = scsi_add_host(host, &pdev->dev); - if (error) + error = lpfc_sli_hba_setup(phba); + if (error) { + error = -ENODEV; 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); - scsi_scan_host(host); + if (phba->cfg_poll & DISABLE_FCP_RING_INT) { + spin_lock_irq(phba->host->host_lock); + lpfc_poll_start_timer(phba); + spin_unlock_irq(phba->host->host_lock); + } + /* + * set fixed host attributes + * Must done after lpfc_sli_hba_setup() + */ + + fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn); + fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn); + fc_host_supported_classes(host) = FC_COS_CLASS3; + + memset(fc_host_supported_fc4s(host), 0, + sizeof(fc_host_supported_fc4s(host))); + fc_host_supported_fc4s(host)[2] = 1; + fc_host_supported_fc4s(host)[7] = 1; + + lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host)); + + fc_host_supported_speeds(host) = 0; + if (phba->lmt & LMT_10Gb) + fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT; + if (phba->lmt & LMT_4Gb) + fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT; + if (phba->lmt & LMT_2Gb) + fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT; + if (phba->lmt & LMT_1Gb) + fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT; + + fc_host_maxframe_size(host) = + ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) | + (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb); + + /* This value is also unchanging */ + memset(fc_host_active_fc4s(host), 0, + sizeof(fc_host_active_fc4s(host))); + fc_host_active_fc4s(host)[2] = 1; + fc_host_active_fc4s(host)[7] = 1; + + spin_lock_irq(phba->host->host_lock); + phba->fc_flag &= ~FC_LOADING; + spin_unlock_irq(phba->host->host_lock); return 0; out_free_irq: @@ -1724,6 +1705,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) phba->work_hba_events = 0; free_irq(phba->pcidev->irq, phba); pci_disable_msi(phba->pcidev); +out_free_sysfs_attr: + lpfc_free_sysfs_attr(phba); +out_remove_host: + fc_remove_host(phba->host); + scsi_remove_host(phba->host); out_kthread_stop: kthread_stop(phba->worker_thread); out_free_iocbq: @@ -1761,8 +1747,56 @@ lpfc_pci_remove_one(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + unsigned long iflag; + + lpfc_free_sysfs_attr(phba); + + spin_lock_irqsave(phba->host->host_lock, iflag); + phba->fc_flag |= FC_UNLOADING; + + spin_unlock_irqrestore(phba->host->host_lock, iflag); - lpfc_remove_device(phba); + fc_remove_host(phba->host); + scsi_remove_host(phba->host); + + kthread_stop(phba->worker_thread); + + /* + * Bring down the SLI Layer. This step disable all interrupts, + * clears the rings, discards all mailbox commands, and resets + * the HBA. + */ + lpfc_sli_hba_down(phba); + lpfc_sli_brdrestart(phba); + + /* Release the irq reservation */ + free_irq(phba->pcidev->irq, phba); + pci_disable_msi(phba->pcidev); + + lpfc_cleanup(phba, 0); + lpfc_stop_timer(phba); + phba->work_hba_events = 0; + + /* + * Call scsi_free before mem_free since scsi bufs are released to their + * corresponding pools here. + */ + lpfc_scsi_free(phba); + lpfc_mem_free(phba); + + /* Free resources associated with SLI2 interface */ + dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, + phba->slim2p, phba->slim2p_mapping); + + /* unmap adapter SLIM and Control Registers */ + iounmap(phba->ctrl_regs_memmap_p); + iounmap(phba->slim_memmap_p); + + pci_release_regions(phba->pcidev); + pci_disable_device(phba->pcidev); + + idr_remove(&lpfc_hba_index, phba->brd_no); + scsi_host_put(phba->host); pci_set_drvdata(pdev, NULL); } @@ -1907,18 +1941,6 @@ static struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S, PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT, - PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID, - PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB, - PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP, - PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP, - PCI_ANY_ID, PCI_ANY_ID, }, - {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S, - PCI_ANY_ID, PCI_ANY_ID, }, { 0 } }; diff --git a/trunk/drivers/scsi/lpfc/lpfc_mbox.c b/trunk/drivers/scsi/lpfc/lpfc_mbox.c index 8041c3f06f7b..4d016c2a1b26 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_mbox.c +++ b/trunk/drivers/scsi/lpfc/lpfc_mbox.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -212,7 +212,6 @@ lpfc_init_link(struct lpfc_hba * phba, case LINK_SPEED_1G: case LINK_SPEED_2G: case LINK_SPEED_4G: - case LINK_SPEED_8G: mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; mb->un.varInitLnk.link_speed = linkspeed; diff --git a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c index b309841e3846..0c7e731dc45a 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -168,13 +168,14 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, * routine effectively results in a "software abort". */ int -lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) +lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, + int send_abts) { - LIST_HEAD(completions); struct lpfc_sli *psli; struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *cmd; + IOCB_t *icmd; + int found = 0; /* Abort outstanding I/O on NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, @@ -187,39 +188,75 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) pring = &psli->ring[LPFC_ELS_RING]; /* First check the txq */ - spin_lock_irq(phba->host->host_lock); - list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { - /* Check to see if iocb matches the nport we are looking - for */ - if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { - /* It matches, so deque and call compl with an - error */ - list_move_tail(&iocb->list, &completions); - pring->txq_cnt--; + do { + found = 0; + spin_lock_irq(phba->host->host_lock); + list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { + /* Check to see if iocb matches the nport we are looking + for */ + if ((lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))) { + found = 1; + /* It matches, so deque and call compl with an + error */ + list_del(&iocb->list); + pring->txq_cnt--; + if (iocb->iocb_cmpl) { + icmd = &iocb->iocb; + icmd->ulpStatus = IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); + (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, iocb); + break; + } } - } + spin_unlock_irq(phba->host->host_lock); + } while (found); + /* Everything on txcmplq will be returned by firmware + * with a no rpi / linkdown / abort error. For ring 0, + * ELS discovery, we want to get rid of it right here. + */ /* Next check the txcmplq */ - list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { - /* Check to see if iocb matches the nport we are looking - for */ - if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); - } - spin_unlock_irq(phba->host->host_lock); - - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del(&iocb->list); - - if (iocb->iocb_cmpl) { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } else - lpfc_sli_release_iocbq(phba, iocb); - } + do { + found = 0; + spin_lock_irq(phba->host->host_lock); + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, + list) { + /* Check to see if iocb matches the nport we are looking + for */ + if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) { + found = 1; + /* It matches, so deque and call compl with an + error */ + list_del(&iocb->list); + pring->txcmplq_cnt--; + + icmd = &iocb->iocb; + /* If the driver is completing an ELS + * command early, flush it out of the firmware. + */ + if (send_abts && + (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) && + (icmd->un.elsreq64.bdl.ulpIoTag32)) { + lpfc_sli_issue_abort_iotag32(phba, + pring, iocb); + } + if (iocb->iocb_cmpl) { + icmd->ulpStatus = IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); + (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, iocb); + break; + } + } + spin_unlock_irq(phba->host->host_lock); + } while(found); /* If we are delaying issuing an ELS command, cancel it */ if (ndlp->nlp_flag & NLP_DELAY_TMO) @@ -353,10 +390,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, * queue this mbox command to be processed later. */ mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; - /* - * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox - * command issued in lpfc_cmpl_els_acc(). - */ + mbox->context2 = ndlp; ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); /* @@ -370,7 +404,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, */ if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); } lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); @@ -437,7 +471,8 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); return 0; } @@ -467,10 +502,12 @@ lpfc_rcv_logo(struct lpfc_hba * phba, ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); } else { ndlp->nlp_prev_state = ndlp->nlp_state; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + ndlp->nlp_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); } spin_lock_irq(phba->host->host_lock); @@ -564,10 +601,11 @@ lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba, if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + ndlp->nlp_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); return ndlp->nlp_state; } - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } @@ -576,7 +614,7 @@ lpfc_rcv_els_unused_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { lpfc_issue_els_logo(phba, ndlp, 0); - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); return ndlp->nlp_state; } @@ -592,7 +630,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_hba * phba, ndlp->nlp_flag |= NLP_LOGO_ACC; spin_unlock_irq(phba->host->host_lock); lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); return ndlp->nlp_state; } @@ -601,7 +639,7 @@ static uint32_t lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } @@ -609,7 +647,7 @@ static uint32_t lpfc_device_rm_unused_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } @@ -659,7 +697,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); return ndlp->nlp_state; @@ -674,7 +712,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); if (evt == NLP_EVT_RCV_LOGO) { lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); @@ -689,7 +727,8 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, spin_unlock_irq(phba->host->host_lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); return ndlp->nlp_state; } @@ -764,26 +803,32 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, goto out; lpfc_unreg_rpi(phba, ndlp); - if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp, - mbox, 0) == 0) { + if (lpfc_reg_login + (phba, irsp->un.elsreq64.remoteID, + (uint8_t *) sp, mbox, 0) == 0) { switch (ndlp->nlp_DID) { case NameServer_DID: - mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; + mbox->mbox_cmpl = + lpfc_mbx_cmpl_ns_reg_login; break; case FDMI_DID: - mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login; + mbox->mbox_cmpl = + lpfc_mbx_cmpl_fdmi_reg_login; break; default: - mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; + mbox->mbox_cmpl = + lpfc_mbx_cmpl_reg_login; } - mbox->context2 = lpfc_nlp_get(ndlp); + mbox->context2 = ndlp; if (lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { - lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); + ndlp->nlp_state = + NLP_STE_REG_LOGIN_ISSUE; + lpfc_nlp_list(phba, ndlp, + NLP_REGLOGIN_LIST); return ndlp->nlp_state; } - lpfc_nlp_put(ndlp); mp = (struct lpfc_dmabuf *)mbox->context1; lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); @@ -796,7 +841,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, out: /* Free this node since the driver cannot login or has the wrong sparm */ - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } @@ -810,9 +855,9 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba, } else { /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } } @@ -823,10 +868,11 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba, uint32_t evt) { /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); spin_unlock_irq(phba->host->host_lock); @@ -842,7 +888,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, struct lpfc_iocbq *cmdiocb; /* software abort outstanding ADISC */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); cmdiocb = (struct lpfc_iocbq *) arg; @@ -850,7 +896,8 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, return ndlp->nlp_state; } ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); return ndlp->nlp_state; @@ -879,7 +926,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; /* software abort outstanding ADISC */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 0); lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); return ndlp->nlp_state; @@ -940,17 +987,20 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name)); ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); lpfc_unreg_rpi(phba, ndlp); return ndlp->nlp_state; } if (ndlp->nlp_type & NLP_FCP_TARGET) { ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE); + ndlp->nlp_state = NLP_STE_MAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); } else { ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } return ndlp->nlp_state; } @@ -966,9 +1016,9 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba, } else { /* software abort outstanding ADISC */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } } @@ -979,10 +1029,11 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba, uint32_t evt) { /* software abort outstanding ADISC */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); ndlp->nlp_flag |= NLP_NPR_ADISC; @@ -1023,36 +1074,9 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, uint32_t evt) { struct lpfc_iocbq *cmdiocb; - LPFC_MBOXQ_t *mb; - LPFC_MBOXQ_t *nextmb; - struct lpfc_dmabuf *mp; cmdiocb = (struct lpfc_iocbq *) arg; - /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ - if ((mb = phba->sli.mbox_active)) { - if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && - (ndlp == (struct lpfc_nodelist *) mb->context2)) { - mb->context2 = NULL; - 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)) { - mp = (struct lpfc_dmabuf *) (mb->context1); - if (mp) { - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - } - list_del(&mb->list); - mempool_free(mb, phba->mbox_mem_pool); - } - } - spin_unlock_irq(phba->host->host_lock); - lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); return ndlp->nlp_state; } @@ -1109,7 +1133,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, */ if (mb->mbxStatus == MBXERR_RPI_FULL) { ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); + ndlp->nlp_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); return ndlp->nlp_state; } @@ -1122,7 +1147,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, lpfc_issue_els_logo(phba, ndlp, 0); ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); return ndlp->nlp_state; } @@ -1131,11 +1157,13 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, /* Only if we are not a fabric nport do we issue PRLI */ if (!(ndlp->nlp_type & NLP_FABRIC)) { ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); + ndlp->nlp_state = NLP_STE_PRLI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST); lpfc_issue_els_prli(phba, ndlp, 0); } else { ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); } return ndlp->nlp_state; } @@ -1150,7 +1178,7 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba, return ndlp->nlp_state; } else { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } } @@ -1161,7 +1189,8 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba, uint32_t evt) { ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); spin_unlock_irq(phba->host->host_lock); @@ -1201,7 +1230,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba, cmdiocb = (struct lpfc_iocbq *) arg; /* Software abort outstanding PRLI before sending acc */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); return ndlp->nlp_state; @@ -1250,7 +1279,8 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, irsp = &rspiocb->iocb; if (irsp->ulpStatus) { ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); + ndlp->nlp_state = NLP_STE_UNMAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST); return ndlp->nlp_state; } @@ -1268,7 +1298,8 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, } ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE); + ndlp->nlp_state = NLP_STE_MAPPED_NODE; + lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST); return ndlp->nlp_state; } @@ -1299,9 +1330,9 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba, } else { /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } } @@ -1328,10 +1359,11 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { /* software abort outstanding PRLI */ - lpfc_els_abort(phba, ndlp); + lpfc_els_abort(phba, ndlp, 1); ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); spin_unlock_irq(phba->host->host_lock); @@ -1404,7 +1436,8 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) { ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); lpfc_disc_set_adisc(phba, ndlp); @@ -1485,7 +1518,8 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba, uint32_t evt) { ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); + ndlp->nlp_state = NLP_STE_NPR_NODE; + lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); spin_lock_irq(phba->host->host_lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); spin_unlock_irq(phba->host->host_lock); @@ -1517,7 +1551,8 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, /* send PLOGI immediately, move to PLOGI issue state */ if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } @@ -1545,13 +1580,16 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(phba->host->host_lock); ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, 0); } else { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } + } return ndlp->nlp_state; } @@ -1589,11 +1627,13 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){ if (ndlp->nlp_flag & NLP_NPR_ADISC) { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); + ndlp->nlp_state = NLP_STE_ADISC_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST); lpfc_issue_els_adisc(phba, ndlp, 0); } else { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); + ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); } } @@ -1642,7 +1682,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba, irsp = &rspiocb->iocb; if (irsp->ulpStatus) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } return ndlp->nlp_state; @@ -1660,7 +1700,7 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba, irsp = &rspiocb->iocb; if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } return ndlp->nlp_state; @@ -1688,7 +1728,7 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba, irsp = &rspiocb->iocb; if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } return ndlp->nlp_state; @@ -1709,7 +1749,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba, ndlp->nlp_rpi = mb->un.varWords[0]; else { if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } } @@ -1725,7 +1765,7 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba, ndlp->nlp_flag |= NLP_NODEV_REMOVE; return ndlp->nlp_state; } - lpfc_drop_node(phba, ndlp); + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); return NLP_STE_FREED_NODE; } @@ -1924,7 +1964,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t); - lpfc_nlp_get(ndlp); + ndlp->nlp_disc_refcnt++; cur_state = ndlp->nlp_state; /* DSM in event on NPort in state */ @@ -1947,7 +1987,18 @@ lpfc_disc_state_machine(struct lpfc_hba * phba, phba->brd_no, rc, ndlp->nlp_DID, ndlp->nlp_flag); - lpfc_nlp_put(ndlp); + ndlp->nlp_disc_refcnt--; + /* Check to see if ndlp removal is deferred */ + if ((ndlp->nlp_disc_refcnt == 0) + && (ndlp->nlp_flag & NLP_DELAY_REMOVE)) { + spin_lock_irq(phba->host->host_lock); + ndlp->nlp_flag &= ~NLP_DELAY_REMOVE; + spin_unlock_irq(phba->host->host_lock); + lpfc_nlp_remove(phba, ndlp); + return NLP_STE_FREED_NODE; + } + if (rc == NLP_STE_FREED_NODE) + return NLP_STE_FREED_NODE; return rc; } diff --git a/trunk/drivers/scsi/lpfc/lpfc_scsi.c b/trunk/drivers/scsi/lpfc/lpfc_scsi.c index 9a12d05e99e4..c3e68e0d8f74 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_scsi.c +++ b/trunk/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -146,10 +146,6 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); - if (lpfc_cmd) { - lpfc_cmd->seg_cnt = 0; - lpfc_cmd->nonsg_phys = 0; - } spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); return lpfc_cmd; } @@ -292,13 +288,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) } static void -lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) +lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) { struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; struct lpfc_hba *phba = lpfc_cmd->scsi_hba; - uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; + uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; uint32_t *lp; @@ -359,24 +355,6 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) be32_to_cpu(fcpcmd->fcpDl), cmnd->resid, fcpi_parm, cmnd->cmnd[0], cmnd->underflow); - /* - * If there is an under run check if under run reported by - * storage array is same as the under run reported by HBA. - * If this is not same, there is a dropped frame. - */ - if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && - fcpi_parm && - (cmnd->resid != fcpi_parm)) { - lpfc_printf_log(phba, KERN_WARNING, - LOG_FCP | LOG_FCP_ERROR, - "%d:0735 FCP Read Check Error and Underrun " - "Data: x%x x%x x%x x%x\n", phba->brd_no, - be32_to_cpu(fcpcmd->fcpDl), - cmnd->resid, - fcpi_parm, cmnd->cmnd[0]); - cmnd->resid = cmnd->request_bufflen; - host_status = DID_ERROR; - } /* * The cmnd->underflow is the minimum number of bytes that must * be transfered for this command. Provided a sense condition @@ -457,7 +435,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, switch (lpfc_cmd->status) { case IOSTAT_FCP_RSP_ERROR: /* Call FCP RSP handler to determine result */ - lpfc_handle_fcp_err(lpfc_cmd,pIocbOut); + lpfc_handle_fcp_err(lpfc_cmd); break; case IOSTAT_NPORT_BSY: case IOSTAT_FABRIC_BSY: @@ -488,10 +466,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, result = cmd->result; sdev = cmd->device; - lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); cmd->scsi_done(cmd); if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { + lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd); return; } @@ -549,6 +527,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } } + lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd); } @@ -691,18 +670,6 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba, return (1); } -static void -lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, - struct lpfc_iocbq *cmdiocbq, - struct lpfc_iocbq *rspiocbq) -{ - struct lpfc_scsi_buf *lpfc_cmd = - (struct lpfc_scsi_buf *) cmdiocbq->context1; - if (lpfc_cmd) - lpfc_release_scsi_buf(phba, lpfc_cmd); - return; -} - static int lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, unsigned tgt_id, unsigned int lun, @@ -739,9 +706,8 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); if (ret != IOCB_SUCCESS) { - if (ret == IOCB_TIMEDOUT) - iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; lpfc_cmd->status = IOSTAT_DRIVER_REJECT; + ret = FAILED; } else { ret = SUCCESS; lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4]; @@ -1008,7 +974,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } static int -lpfc_device_reset_handler(struct scsi_cmnd *cmnd) +lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; @@ -1018,7 +984,6 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_nodelist *pnode = rdata->pnode; uint32_t cmd_result = 0, cmd_status = 0; int ret = FAILED; - int iocb_status = IOCB_SUCCESS; int cnt, loopcnt; lpfc_block_error_handler(cmnd); @@ -1030,7 +995,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) */ while ( 1 ) { if (!pnode) - goto out; + return FAILED; if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { spin_unlock_irq(phba->host->host_lock); @@ -1048,7 +1013,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) } pnode = rdata->pnode; if (!pnode) - goto out; + return FAILED; } if (pnode->nlp_state == NLP_STE_MAPPED_NODE) break; @@ -1063,7 +1028,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) lpfc_cmd->rdata = rdata; ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun, - FCP_TARGET_RESET); + FCP_LUN_RESET); if (!ret) goto out_free_scsi_buf; @@ -1075,21 +1040,16 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) goto out_free_scsi_buf; lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d:0703 Issue target reset to TGT %d LUN %d rpi x%x " - "nlp_flag x%x\n", phba->brd_no, cmnd->device->id, + "%d:0703 Issue LUN Reset to TGT %d LUN %d " + "Data: x%x x%x\n", phba->brd_no, cmnd->device->id, cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); - iocb_status = lpfc_sli_issue_iocb_wait(phba, + ret = lpfc_sli_issue_iocb_wait(phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); - - if (iocb_status == IOCB_TIMEDOUT) - iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; - - if (iocb_status == IOCB_SUCCESS) + if (ret == IOCB_SUCCESS) ret = SUCCESS; - else - ret = iocb_status; + cmd_result = iocbqrsp->iocb.un.ulpWord[4]; cmd_status = iocbqrsp->iocb.ulpStatus; @@ -1127,19 +1087,18 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) if (cnt) { lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d:0719 device reset I/O flush failure: cnt x%x\n", + "%d:0719 LUN Reset I/O flush failure: cnt x%x\n", phba->brd_no, cnt); ret = FAILED; } out_free_scsi_buf: - if (iocb_status != IOCB_TIMEDOUT) { - lpfc_release_scsi_buf(phba, lpfc_cmd); - } + lpfc_release_scsi_buf(phba, lpfc_cmd); + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d:0713 SCSI layer issued device reset (%d, %d) " - "return x%x status x%x result x%x\n", - phba->brd_no, cmnd->device->id, cmnd->device->lun, + "%d:0713 SCSI layer issued LUN reset (%d, %d) " + "Data: x%x x%x x%x\n", + phba->brd_no, cmnd->device->id,cmnd->device->lun, ret, cmd_status, cmd_result); out: @@ -1148,7 +1107,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) } static int -lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) +lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) { struct Scsi_Host *shost = cmnd->device->host; struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; @@ -1175,12 +1134,10 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) * fail, this routine returns failure to the midlayer. */ for (i = 0; i < LPFC_MAX_TARGET; i++) { - /* Search for mapped node by target ID */ + /* Search the mapped list for this target ID */ match = 0; - list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && - i == ndlp->nlp_sid && - ndlp->rport) { + list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { + if ((i == ndlp->nlp_sid) && ndlp->rport) { match = 1; break; } @@ -1195,17 +1152,13 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) "%d:0700 Bus Reset on target %d failed\n", phba->brd_no, i); err_count++; - break; } } - if (ret != IOCB_TIMEDOUT) - lpfc_release_scsi_buf(phba, lpfc_cmd); - if (err_count == 0) ret = SUCCESS; - else - ret = FAILED; + + lpfc_release_scsi_buf(phba, lpfc_cmd); /* * All outstanding txcmplq I/Os should have been aborted by @@ -1346,13 +1299,11 @@ struct scsi_host_template lpfc_template = { .info = lpfc_info, .queuecommand = lpfc_queuecommand, .eh_abort_handler = lpfc_abort_handler, - .eh_device_reset_handler= lpfc_device_reset_handler, - .eh_bus_reset_handler = lpfc_bus_reset_handler, + .eh_device_reset_handler= lpfc_reset_lun_handler, + .eh_bus_reset_handler = lpfc_reset_bus_handler, .slave_alloc = lpfc_slave_alloc, .slave_configure = lpfc_slave_configure, .slave_destroy = lpfc_slave_destroy, - .scan_finished = lpfc_scan_finished, - .scan_start = lpfc_scan_start, .this_id = -1, .sg_tablesize = LPFC_SG_SEG_CNT, .cmd_per_lun = LPFC_CMD_PER_LUN, diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.c b/trunk/drivers/scsi/lpfc/lpfc_sli.c index a1e721459e2b..9fb6960a8ada 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.c +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -528,7 +528,6 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) * If pdone_q is empty, the driver thread gave up waiting and * continued running. */ - pmboxq->mbox_flag |= LPFC_MBX_WAKE; pdone_q = (wait_queue_head_t *) pmboxq->context1; if (pdone_q) wake_up_interruptible(pdone_q); @@ -539,32 +538,11 @@ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { struct lpfc_dmabuf *mp; - uint16_t rpi; - int rc; - mp = (struct lpfc_dmabuf *) (pmb->context1); - if (mp) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } - - /* - * If a REG_LOGIN succeeded after node is destroyed or node - * is in re-discovery driver need to cleanup the RPI. - */ - if (!(phba->fc_flag & FC_UNLOADING) && - (pmb->mb.mbxCommand == MBX_REG_LOGIN64) && - (!pmb->mb.mbxStatus)) { - - rpi = pmb->mb.un.varWords[0]; - lpfc_unreg_login(phba, rpi, pmb); - pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl; - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc != MBX_NOT_FINISHED) - return; - } - mempool_free( pmb, phba->mbox_mem_pool); return; } @@ -715,8 +693,25 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba) } else { spin_unlock_irq(phba->host->host_lock); /* Turn on IOCB processing */ - for (i = 0; i < phba->sli.num_rings; i++) + for (i = 0; i < phba->sli.num_rings; i++) { lpfc_sli_turn_on_ring(phba, i); + } + + /* Free any lpfc_dmabuf's waiting for mbox cmd cmpls */ + while (!list_empty(&phba->freebufList)) { + struct lpfc_dmabuf *mp; + + mp = NULL; + list_remove_head((&phba->freebufList), + mp, + struct lpfc_dmabuf, + list); + if (mp) { + lpfc_mbuf_free(phba, mp->virt, + mp->phys); + kfree(mp); + } + } } } while (process_next); @@ -838,14 +833,6 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, * All other are passed to the completion callback. */ if (pring->ringno == LPFC_ELS_RING) { - if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) { - cmdiocbp->iocb_flag &= - ~LPFC_DRIVER_ABORTED; - saveq->iocb.ulpStatus = - IOSTAT_LOCAL_REJECT; - saveq->iocb.un.ulpWord[4] = - IOERR_SLI_ABORTED; - } spin_unlock_irqrestore(phba->host->host_lock, iflag); (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); @@ -1477,9 +1464,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, int lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { - LIST_HEAD(completions); struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *cmd = NULL; + IOCB_t *icmd = NULL, *cmd = NULL; int errcnt; errcnt = 0; @@ -1488,28 +1474,46 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) * First do the txq. */ spin_lock_irq(phba->host->host_lock); - list_splice_init(&pring->txq, &completions); + list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { + list_del_init(&iocb->list); + if (iocb->iocb_cmpl) { + icmd = &iocb->iocb; + icmd->ulpStatus = IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); + (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irq(phba->host->host_lock); + } else + lpfc_sli_release_iocbq(phba, iocb); + } pring->txq_cnt = 0; + INIT_LIST_HEAD(&(pring->txq)); /* Next issue ABTS for everything on the txcmplq */ - list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { + cmd = &iocb->iocb; - spin_unlock_irq(phba->host->host_lock); + /* + * Imediate abort of IOCB, deque and call compl + */ - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del(&iocb->list); + list_del_init(&iocb->list); + pring->txcmplq_cnt--; if (iocb->iocb_cmpl) { cmd->ulpStatus = IOSTAT_LOCAL_REJECT; cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + spin_unlock_irq(phba->host->host_lock); (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irq(phba->host->host_lock); } else lpfc_sli_release_iocbq(phba, iocb); } + INIT_LIST_HEAD(&pring->txcmplq); + pring->txcmplq_cnt = 0; + spin_unlock_irq(phba->host->host_lock); + return errcnt; } @@ -1584,7 +1588,6 @@ void lpfc_reset_barrier(struct lpfc_hba * phba) hc_copy = readl(phba->HCregaddr); writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr); readl(phba->HCregaddr); /* flush */ - phba->fc_flag |= FC_IGNORE_ERATT; if (readl(phba->HAregaddr) & HA_ERATT) { /* Clear Chip error bit */ @@ -1627,7 +1630,6 @@ void lpfc_reset_barrier(struct lpfc_hba * phba) } restore_hc: - phba->fc_flag &= ~FC_IGNORE_ERATT; writel(hc_copy, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ } @@ -1663,7 +1665,6 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) status &= ~HC_ERINT_ENA; writel(status, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ - phba->fc_flag |= FC_IGNORE_ERATT; spin_unlock_irq(phba->host->host_lock); lpfc_kill_board(phba, pmb); @@ -1673,9 +1674,6 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) if (retval != MBX_SUCCESS) { if (retval != MBX_BUSY) mempool_free(pmb, phba->mbox_mem_pool); - spin_lock_irq(phba->host->host_lock); - phba->fc_flag &= ~FC_IGNORE_ERATT; - spin_unlock_irq(phba->host->host_lock); return 1; } @@ -1702,7 +1700,6 @@ lpfc_sli_brdkill(struct lpfc_hba * phba) } spin_lock_irq(phba->host->host_lock); psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; - phba->fc_flag &= ~FC_IGNORE_ERATT; spin_unlock_irq(phba->host->host_lock); psli->mbox_active = NULL; @@ -1988,6 +1985,42 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba) return rc; } +static void +lpfc_mbox_abort(struct lpfc_hba * phba) +{ + LPFC_MBOXQ_t *pmbox; + MAILBOX_t *mb; + + if (phba->sli.mbox_active) { + del_timer_sync(&phba->sli.mbox_tmo); + phba->work_hba_events &= ~WORKER_MBOX_TMO; + pmbox = phba->sli.mbox_active; + mb = &pmbox->mb; + phba->sli.mbox_active = NULL; + if (pmbox->mbox_cmpl) { + mb->mbxStatus = MBX_NOT_FINISHED; + (pmbox->mbox_cmpl) (phba, pmbox); + } + phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; + } + + /* Abort all the non active mailbox commands. */ + spin_lock_irq(phba->host->host_lock); + pmbox = lpfc_mbox_get(phba); + while (pmbox) { + mb = &pmbox->mb; + if (pmbox->mbox_cmpl) { + mb->mbxStatus = MBX_NOT_FINISHED; + spin_unlock_irq(phba->host->host_lock); + (pmbox->mbox_cmpl) (phba, pmbox); + spin_lock_irq(phba->host->host_lock); + } + pmbox = lpfc_mbox_get(phba); + } + spin_unlock_irq(phba->host->host_lock); + return; +} + /*! lpfc_mbox_timeout * * \pre @@ -2022,8 +2055,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) { LPFC_MBOXQ_t *pmbox; MAILBOX_t *mb; - struct lpfc_sli *psli = &phba->sli; - struct lpfc_sli_ring *pring; spin_lock_irq(phba->host->host_lock); if (!(phba->work_hba_events & WORKER_MBOX_TMO)) { @@ -2031,6 +2062,8 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) return; } + phba->work_hba_events &= ~WORKER_MBOX_TMO; + pmbox = phba->sli.mbox_active; mb = &pmbox->mb; @@ -2045,32 +2078,17 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) phba->sli.sli_flag, phba->sli.mbox_active); - /* Setting state unknown so lpfc_sli_abort_iocb_ring - * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing - * it to fail all oustanding SCSI IO. - */ - phba->hba_state = LPFC_STATE_UNKNOWN; - phba->work_hba_events &= ~WORKER_MBOX_TMO; - phba->fc_flag |= FC_ESTABLISH_LINK; - psli->sli_flag &= ~LPFC_SLI2_ACTIVE; - spin_unlock_irq(phba->host->host_lock); - - pring = &psli->ring[psli->fcp_ring]; - lpfc_sli_abort_iocb_ring(phba, pring); + phba->sli.mbox_active = NULL; + if (pmbox->mbox_cmpl) { + mb->mbxStatus = MBX_NOT_FINISHED; + spin_unlock_irq(phba->host->host_lock); + (pmbox->mbox_cmpl) (phba, pmbox); + spin_lock_irq(phba->host->host_lock); + } + phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "%d:0316 Resetting board due to mailbox timeout\n", - phba->brd_no); - /* - * lpfc_offline calls lpfc_sli_hba_down which will clean up - * on oustanding mailbox commands. - */ - lpfc_offline_prep(phba); - lpfc_offline(phba); - lpfc_sli_brdrestart(phba); - if (lpfc_online(phba) == 0) /* Initialize the HBA */ - mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); - lpfc_unblock_mgmt_io(phba); + spin_unlock_irq(phba->host->host_lock); + lpfc_mbox_abort(phba); return; } @@ -2302,7 +2320,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) spin_unlock_irqrestore(phba->host->host_lock, drvr_flag); - msleep(1); + /* Can be in interrupt context, do not sleep */ + /* (or might be called with interrupts disabled) */ + mdelay(1); spin_lock_irqsave(phba->host->host_lock, drvr_flag); @@ -2410,7 +2430,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) { /* - * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF + * Only CREATE_XRI, CLOSE_XRI, ABORT_XRI, and QUE_RING_BUF * can be issued if the link is not up. */ switch (piocb->iocb.ulpCommand) { @@ -2424,8 +2444,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, piocb->iocb_cmpl = NULL; /*FALLTHROUGH*/ case CMD_CREATE_XRI_CR: - case CMD_CLOSE_XRI_CN: - case CMD_CLOSE_XRI_CX: break; default: goto iocb_busy; @@ -2619,12 +2637,11 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba) int lpfc_sli_hba_down(struct lpfc_hba * phba) { - LIST_HEAD(completions); struct lpfc_sli *psli; struct lpfc_sli_ring *pring; LPFC_MBOXQ_t *pmb; - struct lpfc_iocbq *iocb; - IOCB_t *cmd = NULL; + struct lpfc_iocbq *iocb, *next_iocb; + IOCB_t *icmd = NULL; int i; unsigned long flags = 0; @@ -2632,6 +2649,7 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) lpfc_hba_down_prep(phba); spin_lock_irqsave(phba->host->host_lock, flags); + for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; pring->flag |= LPFC_DEFERRED_RING_EVENT; @@ -2640,25 +2658,28 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) * Error everything on the txq since these iocbs have not been * given to the FW yet. */ - list_splice_init(&pring->txq, &completions); pring->txq_cnt = 0; - } - spin_unlock_irqrestore(phba->host->host_lock, flags); + list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { + list_del_init(&iocb->list); + if (iocb->iocb_cmpl) { + icmd = &iocb->iocb; + icmd->ulpStatus = IOSTAT_LOCAL_REJECT; + icmd->un.ulpWord[4] = IOERR_SLI_DOWN; + spin_unlock_irqrestore(phba->host->host_lock, + flags); + (iocb->iocb_cmpl) (phba, iocb, iocb); + spin_lock_irqsave(phba->host->host_lock, flags); + } else + lpfc_sli_release_iocbq(phba, iocb); + } - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del(&iocb->list); + INIT_LIST_HEAD(&(pring->txq)); - if (iocb->iocb_cmpl) { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_DOWN; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } else - lpfc_sli_release_iocbq(phba, iocb); } + spin_unlock_irqrestore(phba->host->host_lock, flags); + /* Return any active mbox cmds */ del_timer_sync(&psli->mbox_tmo); spin_lock_irqsave(phba->host->host_lock, flags); @@ -2747,138 +2768,85 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } static void -lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, - struct lpfc_iocbq * rspiocb) +lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_iocbq * rspiocb) { - IOCB_t *irsp; - uint16_t abort_iotag, abort_context; - struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb; - struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; - - abort_iocb = NULL; - irsp = &rspiocb->iocb; - - spin_lock_irq(phba->host->host_lock); - - if (irsp->ulpStatus) { - abort_context = cmdiocb->iocb.un.acxri.abortContextTag; - abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag; - - if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag) - abort_iocb = phba->sli.iocbq_lookup[abort_iotag]; - - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0327 Cannot abort els iocb %p" - " with tag %x context %x\n", - phba->brd_no, abort_iocb, - abort_iotag, abort_context); - - /* - * make sure we have the right iocbq before taking it - * off the txcmplq and try to call completion routine. - */ - if (abort_iocb && - abort_iocb->iocb.ulpContext == abort_context && - abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) { - list_del(&abort_iocb->list); - pring->txcmplq_cnt--; - - rsp_ab_iocb = lpfc_sli_get_iocbq(phba); - if (rsp_ab_iocb == NULL) - lpfc_sli_release_iocbq(phba, abort_iocb); - else { - abort_iocb->iocb_flag &= - ~LPFC_DRIVER_ABORTED; - rsp_ab_iocb->iocb.ulpStatus = - IOSTAT_LOCAL_REJECT; - rsp_ab_iocb->iocb.un.ulpWord[4] = - IOERR_SLI_ABORTED; - spin_unlock_irq(phba->host->host_lock); - (abort_iocb->iocb_cmpl) - (phba, abort_iocb, rsp_ab_iocb); - spin_lock_irq(phba->host->host_lock); - lpfc_sli_release_iocbq(phba, rsp_ab_iocb); - } + struct lpfc_dmabuf *buf_ptr, *buf_ptr1; + /* Free the resources associated with the ELS_REQUEST64 IOCB the driver + * just aborted. + * In this case, context2 = cmd, context2->next = rsp, context3 = bpl + */ + if (cmdiocb->context2) { + buf_ptr1 = (struct lpfc_dmabuf *) cmdiocb->context2; + + /* Free the response IOCB before completing the abort + command. */ + buf_ptr = NULL; + list_remove_head((&buf_ptr1->list), buf_ptr, + struct lpfc_dmabuf, list); + if (buf_ptr) { + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); } + lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys); + kfree(buf_ptr1); + } + + if (cmdiocb->context3) { + buf_ptr = (struct lpfc_dmabuf *) cmdiocb->context3; + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); } lpfc_sli_release_iocbq(phba, cmdiocb); - spin_unlock_irq(phba->host->host_lock); return; } int -lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba, - struct lpfc_sli_ring * pring, - struct lpfc_iocbq * cmdiocb) +lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, + struct lpfc_sli_ring * pring, + struct lpfc_iocbq * cmdiocb) { struct lpfc_iocbq *abtsiocbp; IOCB_t *icmd = NULL; IOCB_t *iabt = NULL; - int retval = IOCB_ERROR; - - /* There are certain command types we don't want - * to abort. - */ - icmd = &cmdiocb->iocb; - if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) || - (icmd->ulpCommand == CMD_CLOSE_XRI_CN)) - return 0; - - /* If we're unloading, interrupts are disabled so we - * need to cleanup the iocb here. - */ - if (phba->fc_flag & FC_UNLOADING) - goto abort_iotag_exit; /* issue ABTS for this IOCB based on iotag */ abtsiocbp = lpfc_sli_get_iocbq(phba); if (abtsiocbp == NULL) return 0; - /* This signals the response to set the correct status - * before calling the completion handler. - */ - cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; - iabt = &abtsiocbp->iocb; - iabt->un.acxri.abortType = ABORT_TYPE_ABTS; - iabt->un.acxri.abortContextTag = icmd->ulpContext; - iabt->un.acxri.abortIoTag = icmd->ulpIoTag; - iabt->ulpLe = 1; - iabt->ulpClass = icmd->ulpClass; - - if (phba->hba_state >= LPFC_LINK_UP) - iabt->ulpCommand = CMD_ABORT_XRI_CN; - else - iabt->ulpCommand = CMD_CLOSE_XRI_CN; - - abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; - - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0339 Abort xri x%x, original iotag x%x, abort " - "cmd iotag x%x\n", - phba->brd_no, iabt->un.acxri.abortContextTag, - iabt->un.acxri.abortIoTag, abtsiocbp->iotag); - retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0); + icmd = &cmdiocb->iocb; + switch (icmd->ulpCommand) { + case CMD_ELS_REQUEST64_CR: + /* Even though we abort the ELS command, the firmware may access + * the BPL or other resources before it processes our + * ABORT_MXRI64. Thus we must delay reusing the cmdiocb + * resources till the actual abort request completes. + */ + abtsiocbp->context1 = (void *)((unsigned long)icmd->ulpCommand); + abtsiocbp->context2 = cmdiocb->context2; + abtsiocbp->context3 = cmdiocb->context3; + cmdiocb->context2 = NULL; + cmdiocb->context3 = NULL; + abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl; + break; + default: + lpfc_sli_release_iocbq(phba, abtsiocbp); + return 0; + } -abort_iotag_exit: + iabt->un.amxri.abortType = ABORT_TYPE_ABTS; + iabt->un.amxri.iotag32 = icmd->un.elsreq64.bdl.ulpIoTag32; - /* If we could not issue an abort dequeue the iocb and handle - * the completion here. - */ - if (retval == IOCB_ERROR) { - list_del(&cmdiocb->list); - pring->txcmplq_cnt--; + iabt->ulpLe = 1; + iabt->ulpClass = CLASS3; + iabt->ulpCommand = CMD_ABORT_MXRI64_CN; - if (cmdiocb->iocb_cmpl) { - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - spin_unlock_irq(phba->host->host_lock); - (cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb); - spin_lock_irq(phba->host->host_lock); - } else - lpfc_sli_release_iocbq(phba, cmdiocb); + if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) { + lpfc_sli_release_iocbq(phba, abtsiocbp); + return 0; } return 1; @@ -2950,11 +2918,9 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb) { - unsigned long iflags; - - spin_lock_irqsave(phba->host->host_lock, iflags); + spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, cmdiocb); - spin_unlock_irqrestore(phba->host->host_lock, iflags); + spin_unlock_irq(phba->host->host_lock); return; } @@ -3077,22 +3043,22 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, timeout_req); spin_lock_irq(phba->host->host_lock); - if (piocb->iocb_flag & LPFC_IO_WAKE) { - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0331 IOCB wake signaled\n", - phba->brd_no); - } else if (timeleft == 0) { + if (timeleft == 0) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "%d:0338 IOCB wait timeout error - no " "wake response Data x%x\n", phba->brd_no, timeout); retval = IOCB_TIMEDOUT; - } else { + } else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "%d:0330 IOCB wake NOT set, " "Data x%x x%lx\n", phba->brd_no, timeout, (timeleft / jiffies)); retval = IOCB_TIMEDOUT; + } else { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "%d:0331 IOCB wake signaled\n", + phba->brd_no); } } else { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, @@ -3121,6 +3087,8 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, uint32_t timeout) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); + DECLARE_WAITQUEUE(wq_entry, current); + uint32_t timeleft = 0; int retval; /* The caller must leave context1 empty. */ @@ -3133,25 +3101,27 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, /* setup context field to pass wait_queue pointer to wake function */ pmboxq->context1 = &done_q; + /* start to sleep before we wait, to avoid races */ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&done_q, &wq_entry); + /* now issue the command */ retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); if (retval == MBX_BUSY || retval == MBX_SUCCESS) { - wait_event_interruptible_timeout(done_q, - pmboxq->mbox_flag & LPFC_MBX_WAKE, - timeout * HZ); - + timeleft = schedule_timeout(timeout * HZ); pmboxq->context1 = NULL; - /* - * if LPFC_MBX_WAKE flag is set the mailbox is completed - * else do not free the resources. - */ - if (pmboxq->mbox_flag & LPFC_MBX_WAKE) - retval = MBX_SUCCESS; - else + /* if schedule_timeout returns 0, we timed out and were not + woken up */ + if ((timeleft == 0) || signal_pending(current)) retval = MBX_TIMEOUT; + else + retval = MBX_SUCCESS; } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&done_q, &wq_entry); return retval; } @@ -3214,11 +3184,6 @@ lpfc_intr_handler(int irq, void *dev_id) */ spin_lock(phba->host->host_lock); ha_copy = readl(phba->HAregaddr); - /* If somebody is waiting to handle an eratt don't process it - * here. The brdkill function will do this. - */ - if (phba->fc_flag & FC_IGNORE_ERATT) - ha_copy &= ~HA_ERATT; writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr); readl(phba->HAregaddr); /* flush */ spin_unlock(phba->host->host_lock); diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.h b/trunk/drivers/scsi/lpfc/lpfc_sli.h index 41c38d324ab0..a43549959dc7 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.h +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -39,10 +39,9 @@ struct lpfc_iocbq { IOCB_t iocb; /* IOCB cmd */ uint8_t retry; /* retry counter for IOCB cmd - if needed */ uint8_t iocb_flag; -#define LPFC_IO_LIBDFC 1 /* libdfc iocb */ -#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ -#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */ -#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ +#define LPFC_IO_LIBDFC 1 /* libdfc iocb */ +#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */ +#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */ uint8_t abort_count; uint8_t rsvd2; @@ -68,8 +67,6 @@ struct lpfc_iocbq { #define IOCB_ERROR 2 #define IOCB_TIMEDOUT 3 -#define LPFC_MBX_WAKE 1 - typedef struct lpfcMboxq { /* MBOXQs are used in single linked lists */ struct list_head list; /* ptr to next mailbox command */ @@ -78,7 +75,6 @@ typedef struct lpfcMboxq { void *context2; /* caller context information */ void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *); - uint8_t mbox_flag; } LPFC_MBOXQ_t; diff --git a/trunk/drivers/scsi/lpfc/lpfc_version.h b/trunk/drivers/scsi/lpfc/lpfc_version.h index 92a9107019d2..a61ef3d1e7f1 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_version.h +++ b/trunk/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2007 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -18,12 +18,12 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.12" +#define LPFC_DRIVER_VERSION "8.1.11" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright(c) 2004-2007 Emulex. All rights reserved." +#define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex. All rights reserved." #define DFC_API_VERSION "0.0.0" diff --git a/trunk/drivers/scsi/megaraid.c b/trunk/drivers/scsi/megaraid.c index 3cce75d70263..7fc6e06ea7e1 100644 --- a/trunk/drivers/scsi/megaraid.c +++ b/trunk/drivers/scsi/megaraid.c @@ -1754,8 +1754,7 @@ __mega_busywait_mbox (adapter_t *adapter) for (counter = 0; counter < 10000; counter++) { if (!mbox->m_in.busy) return 0; - udelay(100); - cond_resched(); + udelay(100); yield(); } return -1; /* give up after 1 second */ } @@ -3178,10 +3177,7 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end ) return len; } -#else -static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent) -{ -} + #endif @@ -4346,7 +4342,7 @@ mega_support_cluster(adapter_t *adapter) return 0; } -#ifdef CONFIG_PROC_FS + /** * mega_adapinq() * @adapter - pointer to our soft state @@ -4451,7 +4447,7 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt, return rval; } -#endif + /** * mega_internal_command() @@ -4969,6 +4965,7 @@ megaraid_remove_one(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); adapter_t *adapter = (adapter_t *)host->hostdata; + char buf[12] = { 0 }; scsi_remove_host(host); @@ -5014,11 +5011,8 @@ megaraid_remove_one(struct pci_dev *pdev) remove_proc_entry("raiddrives-30-39", adapter->controller_proc_dir_entry); #endif - { - char buf[12] = { 0 }; - sprintf(buf, "hba%d", adapter->host->host_no); - remove_proc_entry(buf, mega_proc_dir_entry); - } + sprintf(buf, "hba%d", adapter->host->host_no); + remove_proc_entry(buf, mega_proc_dir_entry); } #endif diff --git a/trunk/drivers/scsi/megaraid.h b/trunk/drivers/scsi/megaraid.h index ee70bd4ae4ba..c6e74643abe2 100644 --- a/trunk/drivers/scsi/megaraid.h +++ b/trunk/drivers/scsi/megaraid.h @@ -1002,6 +1002,7 @@ static int megaraid_reset(Scsi_Cmnd *); static int megaraid_abort_and_reset(adapter_t *, Scsi_Cmnd *, int); static int megaraid_biosparam(struct scsi_device *, struct block_device *, sector_t, int []); +static int mega_print_inquiry(char *, char *); static int mega_build_sglist (adapter_t *adapter, scb_t *scb, u32 *buffer, u32 *length); @@ -1023,7 +1024,6 @@ static int mega_init_scb (adapter_t *); static int mega_is_bios_enabled (adapter_t *); #ifdef CONFIG_PROC_FS -static int mega_print_inquiry(char *, char *); static void mega_create_proc_entry(int, struct proc_dir_entry *); static int proc_read_config(char *, char **, off_t, int, int *, void *); static int proc_read_stat(char *, char **, off_t, int, int *, void *); @@ -1040,10 +1040,10 @@ static int proc_rdrv_20(char *, char **, off_t, int, int *, void *); static int proc_rdrv_30(char *, char **, off_t, int, int *, void *); static int proc_rdrv_40(char *, char **, off_t, int, int *, void *); static int proc_rdrv(adapter_t *, char *, int, int); +#endif static int mega_adapinq(adapter_t *, dma_addr_t); static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t); -#endif static int mega_support_ext_cdb(adapter_t *); static mega_passthru* mega_prepare_passthru(adapter_t *, scb_t *, diff --git a/trunk/drivers/scsi/megaraid/megaraid_mm.c b/trunk/drivers/scsi/megaraid/megaraid_mm.c index e075a52ac104..f33a678f0897 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mm.c +++ b/trunk/drivers/scsi/megaraid/megaraid_mm.c @@ -60,7 +60,7 @@ EXPORT_SYMBOL(mraid_mm_unregister_adp); EXPORT_SYMBOL(mraid_mm_adapter_app_handle); static int majorno; -static uint32_t drvr_ver = 0x02200207; +static uint32_t drvr_ver = 0x02200206; static int adapters_count_g; static struct list_head adapters_list_g; diff --git a/trunk/drivers/scsi/mesh.c b/trunk/drivers/scsi/mesh.c index e64d1a19d8d7..cf3666d7d97a 100644 --- a/trunk/drivers/scsi/mesh.c +++ b/trunk/drivers/scsi/mesh.c @@ -185,7 +185,7 @@ struct mesh_state { * Driver is too messy, we need a few prototypes... */ static void mesh_done(struct mesh_state *ms, int start_next); -static void mesh_interrupt(struct mesh_state *ms); +static void mesh_interrupt(int irq, void *dev_id); static void cmd_complete(struct mesh_state *ms); static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd); static void halt_dma(struct mesh_state *ms); @@ -466,7 +466,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd) dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x", MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); - mesh_interrupt(ms); + mesh_interrupt(0, (void *)ms); if (ms->phase != arbitrating) return; } @@ -504,7 +504,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd) dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x", MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); - mesh_interrupt(ms); + mesh_interrupt(0, (void *)ms); if (ms->phase != arbitrating) return; dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x", @@ -1018,11 +1018,10 @@ static void handle_reset(struct mesh_state *ms) static irqreturn_t do_mesh_interrupt(int irq, void *dev_id) { unsigned long flags; - struct mesh_state *ms = dev_id; - struct Scsi_Host *dev = ms->host; + struct Scsi_Host *dev = ((struct mesh_state *)dev_id)->host; spin_lock_irqsave(dev->host_lock, flags); - mesh_interrupt(ms); + mesh_interrupt(irq, dev_id); spin_unlock_irqrestore(dev->host_lock, flags); return IRQ_HANDLED; } @@ -1662,8 +1661,9 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) * handler (do_mesh_interrupt) or by other functions in * exceptional circumstances */ -static void mesh_interrupt(struct mesh_state *ms) +static void mesh_interrupt(int irq, void *dev_id) { + struct mesh_state *ms = (struct mesh_state *) dev_id; volatile struct mesh_regs __iomem *mr = ms->mesh; int intr; diff --git a/trunk/drivers/scsi/qla1280.c b/trunk/drivers/scsi/qla1280.c index 54d8bdf86852..6777e8a69153 100644 --- a/trunk/drivers/scsi/qla1280.c +++ b/trunk/drivers/scsi/qla1280.c @@ -4293,7 +4293,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->devnum = devnum; /* specifies microcode load address */ #ifdef QLA_64BIT_PTR - if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK)) { + if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); diff --git a/trunk/drivers/scsi/qla2xxx/qla_init.c b/trunk/drivers/scsi/qla2xxx/qla_init.c index 2a45aec4ff29..3e296ab845b6 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_init.c +++ b/trunk/drivers/scsi/qla2xxx/qla_init.c @@ -13,6 +13,7 @@ #ifdef CONFIG_SPARC #include +#include #endif /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */ @@ -129,17 +130,18 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) int qla2100_pci_config(scsi_qla_host_t *ha) { - int ret; - uint16_t w; + uint16_t w, mwi; uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + mwi = 0; + if (pci_set_mwi(ha->pdev)) + mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_COMMAND, &w); - w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* Reset expansion ROM address decode enable */ @@ -164,22 +166,22 @@ qla2100_pci_config(scsi_qla_host_t *ha) int qla2300_pci_config(scsi_qla_host_t *ha) { - int ret; - uint16_t w; + uint16_t w, mwi; uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + mwi = 0; + if (pci_set_mwi(ha->pdev)) + mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_COMMAND, &w); - w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); if (IS_QLA2322(ha) || IS_QLA6322(ha)) w &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* * If this is a 2300 card and not 2312, reset the @@ -208,7 +210,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) ha->fb_rev = RD_FB_CMD_REG(ha, reg); if (ha->fb_rev == FPM_2300) - pci_clear_mwi(ha->pdev); + w &= ~PCI_COMMAND_INVALIDATE; /* Deselect FPM registers. */ WRT_REG_WORD(®->ctrl_status, 0x0); @@ -225,6 +227,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); } + pci_write_config_word(ha->pdev, PCI_COMMAND, w); pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); @@ -250,18 +253,19 @@ qla2300_pci_config(scsi_qla_host_t *ha) int qla24xx_pci_config(scsi_qla_host_t *ha) { - int ret; - uint16_t w; + uint16_t w, mwi; uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; int pcix_cmd_reg, pcie_dctl_reg; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + mwi = 0; + if (pci_set_mwi(ha->pdev)) + mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_COMMAND, &w); - w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(ha->pdev, PCI_COMMAND, w); @@ -1396,8 +1400,9 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv) { #ifdef CONFIG_SPARC struct pci_dev *pdev = ha->pdev; - struct device_node *dp = pci_device_to_OF_node(pdev); - const u8 *val; + struct pcidev_cookie *pcp = pdev->sysdata; + struct device_node *dp = pcp->prom_node; + u8 *val; int len; val = of_get_property(dp, "port-wwn", &len); @@ -3368,8 +3373,9 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *n { #ifdef CONFIG_SPARC struct pci_dev *pdev = ha->pdev; - struct device_node *dp = pci_device_to_OF_node(pdev); - const u8 *val; + struct pcidev_cookie *pcp = pdev->sysdata; + struct device_node *dp = pcp->prom_node; + u8 *val; int len; val = of_get_property(dp, "port-wwn", &len); @@ -3925,8 +3931,6 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) return; - if (!ha->fw_major_version) - return; ret = qla2x00_stop_firmware(ha); for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) { diff --git a/trunk/drivers/scsi/qla2xxx/qla_isr.c b/trunk/drivers/scsi/qla2xxx/qla_isr.c index ca463469063d..d4885616cd39 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_isr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_isr.c @@ -1726,17 +1726,6 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "MSI-X: Falling back-to INTa mode -- %d.\n", ret); skip_msix: - - if (!IS_QLA24XX(ha)) - goto skip_msi; - - ret = pci_enable_msi(ha->pdev); - if (!ret) { - DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n")); - ha->flags.msi_enabled = 1; - } -skip_msi: - ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); if (!ret) { @@ -1757,8 +1746,6 @@ qla2x00_free_irqs(scsi_qla_host_t *ha) if (ha->flags.msix_enabled) qla24xx_disable_msix(ha); - else if (ha->flags.inta_enabled) { + else if (ha->flags.inta_enabled) free_irq(ha->host->irq, ha); - pci_disable_msi(ha->pdev); - } } diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index dd076da86a46..b78919a318e2 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -36,7 +36,7 @@ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xlogintimeout, "Login timeout value in seconds."); -int qlport_down_retry; +int qlport_down_retry = 30; module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(qlport_down_retry, "Maximum number of command retries to a port that returns " @@ -1577,7 +1577,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_failed; } - if (qla2x00_initialize_adapter(ha)) { + if (qla2x00_initialize_adapter(ha) && + !(ha->device_flags & DFLG_NO_CABLE)) { + qla_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); diff --git a/trunk/drivers/scsi/qla2xxx/qla_version.h b/trunk/drivers/scsi/qla2xxx/qla_version.h index c375a4efbc71..dc85495c337f 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_version.h +++ b/trunk/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k7" +#define QLA2XXX_VERSION "8.01.07-k6" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 diff --git a/trunk/drivers/scsi/qla4xxx/ql4_dbg.c b/trunk/drivers/scsi/qla4xxx/ql4_dbg.c index 6437d024b0dd..7b4e077a39c1 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_dbg.c @@ -8,8 +8,6 @@ #include "ql4_def.h" #include -#if 0 - static void qla4xxx_print_srb_info(struct srb * srb) { printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags); @@ -197,5 +195,3 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) if (cnt % 16) printk(KERN_DEBUG "\n"); } - -#endif /* 0 */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h index 5b00cb04e7c0..e021eb5db2b2 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h @@ -43,6 +43,8 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, uint16_t *tcp_source_port_num, uint16_t *connection_id); +struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha, + uint32_t fw_ddb_index); int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, dma_addr_t fw_ddb_entry_dma); @@ -53,11 +55,18 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha); struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); int qla4xxx_add_sess(struct ddb_entry *); void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha, + uint16_t fw_ddb_index, + uint16_t connection_id, + uint16_t option); +int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, + uint16_t fw_ddb_index); int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha); int qla4xxx_get_fw_version(struct scsi_qla_host * ha); void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, uint32_t intr_status); int qla4xxx_init_rings(struct scsi_qla_host * ha); +void qla4xxx_dump_buffer(void *b, uint32_t size); struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index); void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb); int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); diff --git a/trunk/drivers/scsi/qla4xxx/ql4_init.c b/trunk/drivers/scsi/qla4xxx/ql4_init.c index 6365df268612..b907b06d72ab 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_init.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_init.c @@ -7,8 +7,9 @@ #include "ql4_def.h" -static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, - uint32_t fw_ddb_index); +/* + * QLogic ISP4xxx Hardware Support Function Prototypes. + */ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) { @@ -47,8 +48,7 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) * This routine deallocates and unlinks the specified ddb_entry from the * adapter's **/ -static void qla4xxx_free_ddb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry) +void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) { /* Remove device entry from list */ list_del_init(&ddb_entry->list); @@ -370,9 +370,9 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, * must be initialized prior to calling this routine * **/ -static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, - uint32_t fw_ddb_index) +int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry, + uint32_t fw_ddb_index) { struct dev_db_entry *fw_ddb_entry = NULL; dma_addr_t fw_ddb_entry_dma; @@ -450,8 +450,8 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, * This routine allocates a ddb_entry, ititializes some values, and * inserts it into the ddb list. **/ -static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, - uint32_t fw_ddb_index) +struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, + uint32_t fw_ddb_index) { struct ddb_entry *ddb_entry; diff --git a/trunk/drivers/scsi/qla4xxx/ql4_iocb.c b/trunk/drivers/scsi/qla4xxx/ql4_iocb.c index a216a1781afb..d41ce380eedc 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_iocb.c @@ -19,8 +19,8 @@ * - advances the request_in pointer * - checks for queue full **/ -static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, - struct queue_entry **queue_entry) +int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, + struct queue_entry **queue_entry) { uint16_t request_in; uint8_t status = QLA_SUCCESS; @@ -62,8 +62,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, * * This routine issues a marker IOCB. **/ -static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun) +int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry, int lun) { struct marker_entry *marker_entry; unsigned long flags = 0; @@ -96,7 +96,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, return status; } -static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( +struct continuation_t1_entry* qla4xxx_alloc_cont_entry( struct scsi_qla_host *ha) { struct continuation_t1_entry *cont_entry; @@ -120,7 +120,7 @@ static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( return cont_entry; } -static uint16_t qla4xxx_calc_request_entries(uint16_t dsds) +uint16_t qla4xxx_calc_request_entries(uint16_t dsds) { uint16_t iocbs; @@ -133,9 +133,9 @@ static uint16_t qla4xxx_calc_request_entries(uint16_t dsds) return iocbs; } -static void qla4xxx_build_scsi_iocbs(struct srb *srb, - struct command_t3_entry *cmd_entry, - uint16_t tot_dsds) +void qla4xxx_build_scsi_iocbs(struct srb *srb, + struct command_t3_entry *cmd_entry, + uint16_t tot_dsds) { struct scsi_qla_host *ha; uint16_t avail_dsds; diff --git a/trunk/drivers/scsi/qla4xxx/ql4_mbx.c b/trunk/drivers/scsi/qla4xxx/ql4_mbx.c index f116ff917237..7f28657eef3f 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_mbx.c @@ -20,9 +20,9 @@ * If outCount is 0, this routine completes successfully WITHOUT waiting * for the mailbox command to complete. **/ -static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, - uint8_t outCount, uint32_t *mbx_cmd, - uint32_t *mbx_sts) +int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, + uint8_t outCount, uint32_t *mbx_cmd, + uint32_t *mbx_sts) { int status = QLA_ERROR; uint8_t i; @@ -170,8 +170,6 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, } -#if 0 - /** * qla4xxx_issue_iocb - issue mailbox iocb command * @ha: adapter state pointer. @@ -245,8 +243,6 @@ int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, return QLA_SUCCESS; } -#endif /* 0 */ - /** * qla4xxx_initialize_fw_cb - initializes firmware control block. * @ha: Pointer to host adapter structure. @@ -574,7 +570,6 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); } -#if 0 int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha, uint16_t fw_ddb_index) { @@ -599,7 +594,6 @@ int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha, return status; } -#endif /* 0 */ /** * qla4xxx_get_crash_record - retrieves crash record. @@ -655,7 +649,6 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha) crash_record, crash_record_dma); } -#if 0 /** * qla4xxx_get_conn_event_log - retrieves connection event log * @ha: Pointer to host adapter structure. @@ -745,7 +738,6 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, event_log_dma); } -#endif /* 0 */ /** * qla4xxx_reset_lun - issues LUN Reset @@ -842,8 +834,7 @@ int qla4xxx_get_fw_version(struct scsi_qla_host * ha) return QLA_SUCCESS; } -static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, - dma_addr_t dma_addr) +int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr) { uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; @@ -864,7 +855,7 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, return QLA_SUCCESS; } -static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) +int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) { uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; diff --git a/trunk/drivers/scsi/qla4xxx/ql4_os.c b/trunk/drivers/scsi/qla4xxx/ql4_os.c index da21f5fbbf87..0bfddf893ed0 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_os.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_os.c @@ -14,7 +14,7 @@ /* * Driver version */ -static char qla4xxx_version_str[40]; +char qla4xxx_version_str[40]; /* * SRB allocation cache @@ -45,7 +45,8 @@ int ql4_mod_unload = 0; /* * SCSI host template entry points */ -static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); + +void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); /* * iSCSI template entry points @@ -1351,7 +1352,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) * At exit, the @ha's flags.enable_64bit_addressing set to indicated * supported addressing method. */ -static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) +void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) { int retval; @@ -1626,7 +1627,7 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); -static struct pci_driver qla4xxx_pci_driver = { +struct pci_driver qla4xxx_pci_driver = { .name = DRIVER_NAME, .id_table = qla4xxx_pci_tbl, .probe = qla4xxx_probe_adapter, diff --git a/trunk/drivers/scsi/scsi_error.c b/trunk/drivers/scsi/scsi_error.c index e8350c562d24..3963e7013bd9 100644 --- a/trunk/drivers/scsi/scsi_error.c +++ b/trunk/drivers/scsi/scsi_error.c @@ -38,6 +38,7 @@ #include "scsi_logging.h" #define SENSE_TIMEOUT (10*HZ) +#define START_UNIT_TIMEOUT (30*HZ) /* * These should *probably* be handled by the host itself. @@ -935,7 +936,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd) for (i = 0; rtn == NEEDS_RETRY && i < 2; i++) rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, - scmd->device->timeout, 0); + START_UNIT_TIMEOUT, 0); if (rtn == SUCCESS) return 0; diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 1f5a07bf2a75..61fbcdcbb009 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -173,7 +173,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) * @retries: number of times to retry request * @flags: or into request flags; * - * returns the req->errors value which is the scsi_cmnd result + * returns the req->errors value which is the the scsi_cmnd result * field. **/ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, diff --git a/trunk/drivers/scsi/scsi_transport_fc.c b/trunk/drivers/scsi/scsi_transport_fc.c index b4d1ece46f78..14c4f065b2b8 100644 --- a/trunk/drivers/scsi/scsi_transport_fc.c +++ b/trunk/drivers/scsi/scsi_transport_fc.c @@ -1718,12 +1718,31 @@ fc_starget_delete(struct work_struct *work) struct fc_rport *rport = container_of(work, struct fc_rport, stgt_delete_work); struct Scsi_Host *shost = rport_to_shost(rport); + unsigned long flags; struct fc_internal *i = to_fc_internal(shost->transportt); - /* Involve the LLDD if possible to terminate all io on the rport. */ - if (i->f->terminate_rport_io) + /* + * Involve the LLDD if possible. All io on the rport is to + * be terminated, either as part of the dev_loss_tmo callback + * processing, or via the terminate_rport_io function. + */ + if (i->f->dev_loss_tmo_callbk) + i->f->dev_loss_tmo_callbk(rport); + else if (i->f->terminate_rport_io) i->f->terminate_rport_io(rport); + spin_lock_irqsave(shost->host_lock, flags); + if (rport->flags & FC_RPORT_DEVLOSS_PENDING) { + spin_unlock_irqrestore(shost->host_lock, flags); + if (!cancel_delayed_work(&rport->fail_io_work)) + fc_flush_devloss(shost); + if (!cancel_delayed_work(&rport->dev_loss_work)) + fc_flush_devloss(shost); + spin_lock_irqsave(shost->host_lock, flags); + rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; + } + spin_unlock_irqrestore(shost->host_lock, flags); + scsi_remove_target(&rport->dev); } @@ -1741,7 +1760,6 @@ fc_rport_final_delete(struct work_struct *work) struct device *dev = &rport->dev; struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); - unsigned long flags; /* * if a scan is pending, flush the SCSI Host work_q so that @@ -1750,37 +1768,13 @@ fc_rport_final_delete(struct work_struct *work) if (rport->flags & FC_RPORT_SCAN_PENDING) scsi_flush_work(shost); - /* involve the LLDD to terminate all pending i/o */ - if (i->f->terminate_rport_io) - i->f->terminate_rport_io(rport); - - /* - * Cancel any outstanding timers. These should really exist - * only when rmmod'ing the LLDD and we're asking for - * immediate termination of the rports - */ - spin_lock_irqsave(shost->host_lock, flags); - if (rport->flags & FC_RPORT_DEVLOSS_PENDING) { - spin_unlock_irqrestore(shost->host_lock, flags); - if (!cancel_delayed_work(&rport->fail_io_work)) - fc_flush_devloss(shost); - if (!cancel_delayed_work(&rport->dev_loss_work)) - fc_flush_devloss(shost); - spin_lock_irqsave(shost->host_lock, flags); - rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; - } - spin_unlock_irqrestore(shost->host_lock, flags); - /* Delete SCSI target and sdevs */ if (rport->scsi_target_id != -1) fc_starget_delete(&rport->stgt_delete_work); - - /* - * Notify the driver that the rport is now dead. The LLDD will - * also guarantee that any communication to the rport is terminated - */ - if (i->f->dev_loss_tmo_callbk) + else if (i->f->dev_loss_tmo_callbk) i->f->dev_loss_tmo_callbk(rport); + else if (i->f->terminate_rport_io) + i->f->terminate_rport_io(rport); transport_remove_device(dev); device_del(dev); @@ -1969,6 +1963,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } if (match) { + struct delayed_work *work = + &rport->dev_loss_work; memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); @@ -1986,61 +1982,46 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, fci->f->dd_fcrport_size); /* - * If we were not a target, cancel the - * io terminate and rport timers, and - * we're done. - * - * If we were a target, but our new role - * doesn't indicate a target, leave the - * timers running expecting the role to - * change as the target fully logs in. If - * it doesn't, the target will be torn down. - * - * If we were a target, and our role shows - * we're still a target, cancel the timers - * and kick off a scan. + * If we were blocked, we were a target. + * If no longer a target, we leave the timer + * running in case the port changes roles + * prior to the timer expiring. If the timer + * fires, the target will be torn down. */ - - /* was a target, not in roles */ - if ((rport->scsi_target_id != -1) && - (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET))) + if (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)) return rport; + /* restart the target */ + /* - * Stop the fail io and dev_loss timers. - * If they flush, the port_state will - * be checked and will NOOP the function. + * Stop the target timers first. Take no action + * on the del_timer failure as the state + * machine state change will validate the + * transaction. */ if (!cancel_delayed_work(&rport->fail_io_work)) fc_flush_devloss(shost); - if (!cancel_delayed_work(&rport->dev_loss_work)) + if (!cancel_delayed_work(work)) fc_flush_devloss(shost); spin_lock_irqsave(shost->host_lock, flags); rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; - /* if target, initiate a scan */ - if (rport->scsi_target_id != -1) { - rport->flags |= FC_RPORT_SCAN_PENDING; - scsi_queue_work(shost, - &rport->scan_work); - spin_unlock_irqrestore(shost->host_lock, - flags); - scsi_target_unblock(&rport->dev); - } else - spin_unlock_irqrestore(shost->host_lock, - flags); + /* initiate a scan of the target */ + rport->flags |= FC_RPORT_SCAN_PENDING; + scsi_queue_work(shost, &rport->scan_work); + + spin_unlock_irqrestore(shost->host_lock, flags); + + scsi_target_unblock(&rport->dev); return rport; } } } - /* - * Search the bindings array - * Note: if never a FCP target, you won't be on this list - */ + /* Search the bindings array */ if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) { /* search for a matching consistent binding */ @@ -2177,24 +2158,15 @@ fc_remote_port_delete(struct fc_rport *rport) spin_lock_irqsave(shost->host_lock, flags); - if (rport->port_state != FC_PORTSTATE_ONLINE) { + /* If no scsi target id mapping, delete it */ + if (rport->scsi_target_id == -1) { + list_del(&rport->peers); + rport->port_state = FC_PORTSTATE_DELETED; + fc_queue_work(shost, &rport->rport_delete_work); spin_unlock_irqrestore(shost->host_lock, flags); return; } - /* - * In the past, we if this was not an FCP-Target, we would - * unconditionally just jump to deleting the rport. - * However, rports can be used as node containers by the LLDD, - * and its not appropriate to just terminate the rport at the - * first sign of a loss in connectivity. The LLDD may want to - * send ELS traffic to re-validate the login. If the rport is - * immediately deleted, it makes it inappropriate for a node - * container. - * So... we now unconditionally wait dev_loss_tmo before - * destroying an rport. - */ - rport->port_state = FC_PORTSTATE_BLOCKED; rport->flags |= FC_RPORT_DEVLOSS_PENDING; @@ -2291,11 +2263,11 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) EXPORT_SYMBOL(fc_remote_port_rolechg); /** - * fc_timeout_deleted_rport - Timeout handler for a deleted remote port, - * which we blocked, and has now failed to return - * in the allotted time. + * fc_timeout_deleted_rport - Timeout handler for a deleted remote port that + * was a SCSI target (thus was blocked), and failed + * to return in the alloted time. * - * @work: rport target that failed to reappear in the allotted time. + * @work: rport target that failed to reappear in the alloted time. **/ static void fc_timeout_deleted_rport(struct work_struct *work) @@ -2311,12 +2283,10 @@ fc_timeout_deleted_rport(struct work_struct *work) rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; /* - * If the port is ONLINE, then it came back. If it was a SCSI - * target, validate it still is. If not, tear down the - * scsi_target on it. + * If the port is ONLINE, then it came back. Validate it's still an + * FCP target. If not, tear down the scsi_target on it. */ if ((rport->port_state == FC_PORTSTATE_ONLINE) && - (rport->scsi_target_id != -1) && !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { dev_printk(KERN_ERR, &rport->dev, "blocked FC remote port time out: no longer" @@ -2327,24 +2297,18 @@ fc_timeout_deleted_rport(struct work_struct *work) return; } - /* NOOP state - we're flushing workq's */ if (rport->port_state != FC_PORTSTATE_BLOCKED) { spin_unlock_irqrestore(shost->host_lock, flags); dev_printk(KERN_ERR, &rport->dev, - "blocked FC remote port time out: leaving" - " rport%s alone\n", - (rport->scsi_target_id != -1) ? " and starget" : ""); + "blocked FC remote port time out: leaving target alone\n"); return; } - if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) || - (rport->scsi_target_id == -1)) { + if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) { list_del(&rport->peers); rport->port_state = FC_PORTSTATE_DELETED; dev_printk(KERN_ERR, &rport->dev, - "blocked FC remote port time out: removing" - " rport%s\n", - (rport->scsi_target_id != -1) ? " and starget" : ""); + "blocked FC remote port time out: removing target\n"); fc_queue_work(shost, &rport->rport_delete_work); spin_unlock_irqrestore(shost->host_lock, flags); return; diff --git a/trunk/drivers/scsi/tmscsim.c b/trunk/drivers/scsi/tmscsim.c index e7b85e832eb5..3158949ffa62 100644 --- a/trunk/drivers/scsi/tmscsim.c +++ b/trunk/drivers/scsi/tmscsim.c @@ -351,27 +351,6 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; * (DCBs, SRBs, Queueing) * **********************************************************************/ -static void inline dc390_start_segment(struct dc390_srb* pSRB) -{ - struct scatterlist *psgl = pSRB->pSegmentList; - - /* start new sg segment */ - pSRB->SGBusAddr = sg_dma_address(psgl); - pSRB->SGToBeXferLen = sg_dma_len(psgl); -} - -static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue) -{ - unsigned long xfer = pSRB->SGToBeXferLen - residue; - - /* xfer more bytes transferred */ - pSRB->SGBusAddr += xfer; - pSRB->TotalXferredLen += xfer; - pSRB->SGToBeXferLen = residue; - - return xfer; -} - static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) { struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL; @@ -646,6 +625,70 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr return 0; } +//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ +#define DMA_INT 0 + +#if DMA_INT +/* This is similar to AM53C974.c ... */ +static u8 +dc390_dma_intr (struct dc390_acb* pACB) +{ + struct dc390_srb* pSRB; + u8 dstate; + DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev); + + DEBUG0(pci_read_config_word(pdev, PCI_STATUS, &pstate)); + DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\ + { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \ + pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));}); + + dstate = DC390_read8 (DMA_Status); + + if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate; + else pSRB = pACB->pActiveDCB->pActiveSRB; + + if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT)) + { + printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate); + return dstate; + } + if (dstate & DMA_XFER_DONE) + { + u32 residual, xferCnt; int ctr = 6000000; + if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION)) + { + do + { + DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n")); + dstate = DC390_read8 (DMA_Status); + residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 | + DC390_read8 (CtcReg_High) << 16; + residual += DC390_read8 (Current_Fifo) & 0x1f; + } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr); + if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + /* residual = ... */ + } + else + residual = 0; + + /* ??? */ + + xferCnt = pSRB->SGToBeXferLen - residual; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = residual; +# ifdef DC390_DEBUG0 + printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n", + (unsigned int)residual, (unsigned int)xferCnt); +# endif + + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + } + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; + return dstate; +} +#endif + static void __inline__ dc390_InvalidCmd(struct dc390_acb* pACB) @@ -665,6 +708,9 @@ DC390_Interrupt(void *dev_id) u8 phase; void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *); u8 istate, istatus; +#if DMA_INT + u8 dstatus; +#endif sstatus = DC390_read8 (Scsi_Status); if( !(sstatus & INTERRUPT) ) @@ -672,9 +718,22 @@ DC390_Interrupt(void *dev_id) DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus)); +#if DMA_INT + spin_lock_irq(pACB->pScsiHost->host_lock); + dstatus = dc390_dma_intr (pACB); + spin_unlock_irq(pACB->pScsiHost->host_lock); + + DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus)); + if (! (dstatus & SCSI_INTERRUPT)) + { + DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); + return IRQ_NONE; + } +#else //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); //dstatus = DC390_read8 (DMA_Status); //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); +#endif spin_lock_irq(pACB->pScsiHost->host_lock); @@ -762,10 +821,11 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id) } static void -dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) { u8 sstatus; - u32 ResidCnt; + struct scatterlist *psgl; + u32 ResidCnt, xferCnt; u8 dstate = 0; sstatus = *psstatus; @@ -796,35 +856,42 @@ dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; - dc390_start_segment(pSRB); + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); } else pSRB->SGToBeXferLen = 0; } else { - ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) + - (((u32) DC390_read8 (CtcReg_High) << 16) | - ((u32) DC390_read8 (CtcReg_Mid) << 8) | - (u32) DC390_read8 (CtcReg_Low)); - - dc390_advance_segment(pSRB, ResidCnt); + ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f; + ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16; + ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; + ResidCnt += (u32) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; } } if ((*psstatus & 7) != SCSI_DATA_OUT) { - DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); + DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); } } static void -dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) { u8 sstatus, residual, bval; - u32 ResidCnt, i; + struct scatterlist *psgl; + u32 ResidCnt, i; unsigned long xferCnt; + u8 *ptr; sstatus = *psstatus; @@ -855,17 +922,19 @@ dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \ + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \ + ((unsigned long) DC390_read8 (CtcReg_Low))); - DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen)); + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen)); - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ pSRB->TotalXferredLen += pSRB->SGToBeXferLen; pSRB->SGIndex++; if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; - dc390_start_segment(pSRB); + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); } else pSRB->SGToBeXferLen = 0; @@ -904,45 +973,47 @@ dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) } /* It seems a DMA Blast abort isn't that bad ... */ if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); - //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); - dc390_laststatus &= ~0xff000000; - dc390_laststatus |= bval << 24; + //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval)); - ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) | - ((u32) DC390_read8 (CtcReg_Mid) << 8)) | - (u32) DC390_read8 (CtcReg_Low); - - xferCnt = dc390_advance_segment(pSRB, ResidCnt); - - if (residual) { - size_t count = 1; - size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList); - unsigned long flags; - u8 *ptr; - + ResidCnt = (u32) DC390_read8 (CtcReg_High); + ResidCnt <<= 8; + ResidCnt |= (u32) DC390_read8 (CtcReg_Mid); + ResidCnt <<= 8; + ResidCnt |= (u32) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + + if( residual ) + { + static int feedback_requested; bval = DC390_read8 (ScsiFifo); /* get one residual byte */ - local_irq_save(flags); - ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count); - if (likely(ptr)) { - *(ptr + offset) = bval; - scsi_kunmap_atomic_sg(ptr); + if (!feedback_requested) { + feedback_requested = 1; + printk(KERN_WARNING "%s: Please, contact " + "to help improve support for your system.\n", __FILE__); } - local_irq_restore(flags); - WARN_ON(!ptr); - /* 1 more byte read */ - xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1); + ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr ); + *ptr = bval; + pSRB->SGBusAddr++; xferCnt++; + pSRB->TotalXferredLen++; + pSRB->SGToBeXferLen--; } - DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\ + DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ pSRB->TotalXferredLen, pSRB->SGToBeXferLen)); + } } if ((*psstatus & 7) != SCSI_DATA_IN) { DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ } } @@ -1145,7 +1216,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB) /* handle RESTORE_PTR */ -/* This doesn't look very healthy... to-be-fixed */ +/* I presume, this command is already mapped, so, have to remap. */ static void dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) { @@ -1154,7 +1225,6 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) pSRB->TotalXferredLen = 0; pSRB->SGIndex = 0; if (pcmd->use_sg) { - size_t saved; pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; psgl = pSRB->pSegmentList; //dc390_pci_sync(pSRB); @@ -1166,16 +1236,15 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; - - dc390_start_segment(pSRB); + psgl = pSRB->pSegmentList; + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); } else pSRB->SGToBeXferLen = 0; } - - saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen; - pSRB->SGToBeXferLen -= saved; - pSRB->SGBusAddr += saved; + pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen); printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); @@ -1296,6 +1365,7 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) static void dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) { + struct scatterlist *psgl; unsigned long lval; struct dc390_dcb* pDCB = pACB->pActiveDCB; @@ -1321,11 +1391,12 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) if( pSRB->SGIndex < pSRB->SGcount ) { - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */); if( !pSRB->SGToBeXferLen ) { - dc390_start_segment(pSRB); - + psgl = pSRB->pSegmentList; + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.")); } lval = pSRB->SGToBeXferLen; @@ -1339,12 +1410,12 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen); DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr); - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ pSRB->SRBState = SRB_DATA_XFER; DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir); + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT)); //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status))); //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT)); @@ -1365,8 +1436,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) pSRB->SRBState |= SRB_XFERPAD; DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE); /* - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT; + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); */ } } diff --git a/trunk/drivers/scsi/tmscsim.h b/trunk/drivers/scsi/tmscsim.h index c3d8c80cfb38..9b66fa8d38d9 100644 --- a/trunk/drivers/scsi/tmscsim.h +++ b/trunk/drivers/scsi/tmscsim.h @@ -19,6 +19,14 @@ #define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ +#define pci_dma_lo32(a) (a & 0xffffffff) + +typedef u8 UCHAR; /* 8 bits */ +typedef u16 USHORT; /* 16 bits */ +typedef u32 UINT; /* 32 bits */ +typedef unsigned long ULONG; /* 32/64 bits */ + + /* ;----------------------------------------------------------------------- ; SCSI Request Block @@ -35,9 +43,7 @@ struct scatterlist *pSegmentList; struct scatterlist Segmentx; /* make a one entry of S/G list table */ -unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A - in CPU endianness. We're only getting 32-bit bus - addresses by default */ +unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A*/ unsigned long SGToBeXferLen; /*; to be xfer length */ unsigned long TotalXferredLen; unsigned long SavedTotXLen; diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index a6f5bfbb777b..e8efe938c4e7 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -5,7 +5,6 @@ # menu "Serial drivers" - depends on HAS_IOMEM # # The new 8250/16550 serial drivers diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart.h b/trunk/drivers/serial/cpm_uart/cpm_uart.h index a8f894c78194..69715e556506 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart.h +++ b/trunk/drivers/serial/cpm_uart/cpm_uart.h @@ -88,7 +88,7 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; /* these are located in their respective files */ void cpm_line_cr_cmd(int line, int cmd); -int cpm_uart_init_portdesc(void); +int __init cpm_uart_init_portdesc(void); int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); void cpm_uart_freebuf(struct uart_cpm_port *pinfo); diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart_core.c b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c index b63ff8dd7304..f23972bc00c0 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c @@ -482,8 +482,7 @@ static void cpm_uart_shutdown(struct uart_port *port) } static void cpm_uart_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) + struct termios *termios, struct termios *old) { int baud; unsigned long flags; diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 8c6324ed0202..925fb607d8c4 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/trunk/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -125,7 +125,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) { int dpmemsz, memsz; u8 *dp_mem; - unsigned long dp_offset; + uint dp_offset; u8 *mem_addr; dma_addr_t dma_addr = 0; @@ -133,7 +133,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos); dp_offset = cpm_dpalloc(dpmemsz, 8); - if (IS_ERR_VALUE(dp_offset)) { + if (IS_DPERR(dp_offset)) { printk(KERN_ERR "cpm_uart_cpm1.c: could not allocate buffer descriptors\n"); return -ENOMEM; @@ -185,7 +185,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) } /* Setup any dynamic params in the uart desc */ -int cpm_uart_init_portdesc(void) +int __init cpm_uart_init_portdesc(void) { pr_debug("CPM uart[-]:init portdesc\n"); diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/trunk/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 7b61d805ebe9..fa455996ad8f 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/trunk/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -222,7 +222,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) { int dpmemsz, memsz; u8 *dp_mem; - unsigned long dp_offset; + uint dp_offset; u8 *mem_addr; dma_addr_t dma_addr = 0; @@ -230,7 +230,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos); dp_offset = cpm_dpalloc(dpmemsz, 8); - if (IS_ERR_VALUE(dp_offset)) { + if (IS_DPERR(dp_offset)) { printk(KERN_ERR "cpm_uart_cpm.c: could not allocate buffer descriptors\n"); return -ENOMEM; @@ -282,7 +282,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) } /* Setup any dynamic params in the uart desc */ -int cpm_uart_init_portdesc(void) +int __init cpm_uart_init_portdesc(void) { #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2) u16 *addr; diff --git a/trunk/drivers/serial/sunzilog.c b/trunk/drivers/serial/sunzilog.c index 0985193dc57d..da73205e54cd 100644 --- a/trunk/drivers/serial/sunzilog.c +++ b/trunk/drivers/serial/sunzilog.c @@ -92,8 +92,6 @@ struct uart_sunzilog_port { #define SUNZILOG_FLAG_REGS_HELD 0x00000040 #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 -#define SUNZILOG_FLAG_ESCC 0x00000200 -#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400 unsigned int cflag; @@ -176,11 +174,9 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) /* This function must only be called when the TX is not busy. The UART * port lock must be held and local interrupts disabled. */ -static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) +static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) { int i; - int escc; - unsigned char r15; /* Let pending transmits finish. */ for (i = 0; i < 1000; i++) { @@ -233,25 +229,11 @@ static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *r write_zsreg(channel, R14, regs[R14]); /* External status interrupt control. */ - write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN); - - /* ESCC Extension Register */ - r15 = read_zsreg(channel, R15); - if (r15 & 0x01) { - write_zsreg(channel, R7, regs[R7p]); - - /* External status interrupt and FIFO control. */ - write_zsreg(channel, R15, regs[R15] & ~WR7pEN); - escc = 1; - } else { - /* Clear FIFO bit case it is an issue */ - regs[R15] &= ~FIFOEN; - escc = 0; - } + write_zsreg(channel, R15, regs[R15]); /* Reset external status interrupts. */ - write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */ - write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */ + write_zsreg(channel, R0, RES_EXT_INT); + write_zsreg(channel, R0, RES_EXT_INT); /* Rewrite R3/R5, this time without enables masked. */ write_zsreg(channel, R3, regs[R3]); @@ -259,8 +241,6 @@ static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *r /* Rewrite R1, this time without IRQ enabled masked. */ write_zsreg(channel, R1, regs[R1]); - - return escc; } /* Reprogram the Zilog channel HW registers with the copies found in the @@ -751,7 +731,7 @@ static void sunzilog_enable_ms(struct uart_port *port) up->curregs[R15] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ - write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN); + write_zsreg(channel, R15, up->curregs[R15]); } } @@ -881,44 +861,44 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, up->curregs[R14] = BRSRC | BRENAB; /* Character size, stop bits, and parity. */ - up->curregs[R3] &= ~RxN_MASK; - up->curregs[R5] &= ~TxN_MASK; + up->curregs[3] &= ~RxN_MASK; + up->curregs[5] &= ~TxN_MASK; switch (cflag & CSIZE) { case CS5: - up->curregs[R3] |= Rx5; - up->curregs[R5] |= Tx5; + up->curregs[3] |= Rx5; + up->curregs[5] |= Tx5; up->parity_mask = 0x1f; break; case CS6: - up->curregs[R3] |= Rx6; - up->curregs[R5] |= Tx6; + up->curregs[3] |= Rx6; + up->curregs[5] |= Tx6; up->parity_mask = 0x3f; break; case CS7: - up->curregs[R3] |= Rx7; - up->curregs[R5] |= Tx7; + up->curregs[3] |= Rx7; + up->curregs[5] |= Tx7; up->parity_mask = 0x7f; break; case CS8: default: - up->curregs[R3] |= Rx8; - up->curregs[R5] |= Tx8; + up->curregs[3] |= Rx8; + up->curregs[5] |= Tx8; up->parity_mask = 0xff; break; }; - up->curregs[R4] &= ~0x0c; + up->curregs[4] &= ~0x0c; if (cflag & CSTOPB) - up->curregs[R4] |= SB2; + up->curregs[4] |= SB2; else - up->curregs[R4] |= SB1; + up->curregs[4] |= SB1; if (cflag & PARENB) - up->curregs[R4] |= PAR_ENAB; + up->curregs[4] |= PAR_ENAB; else - up->curregs[R4] &= ~PAR_ENAB; + up->curregs[4] &= ~PAR_ENAB; if (!(cflag & PARODD)) - up->curregs[R4] |= PAR_EVEN; + up->curregs[4] |= PAR_EVEN; else - up->curregs[R4] &= ~PAR_EVEN; + up->curregs[4] &= ~PAR_EVEN; up->port.read_status_mask = Rx_OVR; if (iflag & INPCK) @@ -972,9 +952,7 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, static const char *sunzilog_type(struct uart_port *port) { - struct uart_sunzilog_port *up = UART_ZILOG(port); - - return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs"; + return "zs"; } /* We do not request/release mappings of the registers here, this @@ -1192,7 +1170,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) spin_lock_irqsave(&up->port.lock, flags); - up->curregs[R15] |= BRKIE; + up->curregs[R15] = BRKIE; sunzilog_convert_to_zs(up, con->cflag, 0, brg); sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); @@ -1251,7 +1229,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe baud = 4800; } - up->curregs[R15] |= BRKIE; + up->curregs[R15] = BRKIE; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); sunzilog_convert_to_zs(up, up->cflag, 0, brg); sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); @@ -1305,18 +1283,8 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | SUNZILOG_FLAG_CONS_MOUSE)) { - up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - up->curregs[R4] = PAR_EVEN | X16CLK | SB1; - up->curregs[R3] = RxENAB | Rx8; - up->curregs[R5] = TxENAB | Tx8; - up->curregs[R6] = 0x00; /* SDLC Address */ - up->curregs[R7] = 0x7E; /* SDLC Flag */ - up->curregs[R9] = NV; - up->curregs[R7p] = 0x00; sunzilog_init_kbdms(up, up->port.line); - /* Only enable interrupts if an ISR handler available */ - if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) - up->curregs[R9] |= MIE; + up->curregs[R9] |= (NV | MIE); write_zsreg(channel, R9, up->curregs[R9]); } else { /* Normal serial TTY. */ @@ -1325,9 +1293,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) up->curregs[R4] = PAR_EVEN | X16CLK | SB1; up->curregs[R3] = RxENAB | Rx8; up->curregs[R5] = TxENAB | Tx8; - up->curregs[R6] = 0x00; /* SDLC Address */ - up->curregs[R7] = 0x7E; /* SDLC Flag */ - up->curregs[R9] = NV; + up->curregs[R9] = NV | MIE; up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; baud = 9600; @@ -1335,14 +1301,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRSRC | BRENAB; - up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */ - up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL; - if (__load_zsregs(channel, up->curregs)) { - up->flags |= SUNZILOG_FLAG_ESCC; - } - /* Only enable interrupts if an ISR handler available */ - if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) - up->curregs[R9] |= MIE; + __load_zsregs(channel, up->curregs); write_zsreg(channel, R9, up->curregs[R9]); } @@ -1431,14 +1390,12 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m return err; } } else { - printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) " - "is a %s\n", - op->dev.bus_id, up[0].port.mapbase, op->irqs[0], - sunzilog_type (&up[0].port)); - printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) " - "is a %s\n", - op->dev.bus_id, up[1].port.mapbase, op->irqs[0], - sunzilog_type (&up[1].port)); + printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[0].port.mapbase, op->irqs[0]); + printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[1].port.mapbase, op->irqs[0]); } dev_set_drvdata(&op->dev, &up[0]); @@ -1530,23 +1487,10 @@ static int __init sunzilog_init(void) goto out_unregister_uart; if (zilog_irq != -1) { - struct uart_sunzilog_port *up = sunzilog_irq_chain; err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, "zs", sunzilog_irq_chain); if (err) goto out_unregister_driver; - - /* Enable Interrupts */ - while (up) { - struct zilog_channel __iomem *channel; - - /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */ - channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - up->flags |= SUNZILOG_FLAG_ISR_HANDLER; - up->curregs[R9] |= MIE; - write_zsreg(channel, R9, up->curregs[R9]); - up = up->next; - } } out: @@ -1571,20 +1515,6 @@ static void __exit sunzilog_exit(void) of_unregister_driver(&zs_driver); if (zilog_irq != -1) { - struct uart_sunzilog_port *up = sunzilog_irq_chain; - - /* Disable Interrupts */ - while (up) { - struct zilog_channel __iomem *channel; - - /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */ - channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER; - up->curregs[R9] &= ~MIE; - write_zsreg(channel, R9, up->curregs[R9]); - up = up->next; - } - free_irq(zilog_irq, sunzilog_irq_chain); zilog_irq = -1; } diff --git a/trunk/drivers/serial/sunzilog.h b/trunk/drivers/serial/sunzilog.h index 5dec7b47cc38..7939b6d71270 100644 --- a/trunk/drivers/serial/sunzilog.h +++ b/trunk/drivers/serial/sunzilog.h @@ -13,8 +13,7 @@ struct zilog_layout { struct zilog_channel channelA; }; -#define NUM_ZSREGS 17 -#define R7p 16 /* Written as R7 with P15 bit 0 set */ +#define NUM_ZSREGS 16 /* Conversion routines to/from brg time constants from/to bits * per second. @@ -128,15 +127,6 @@ struct zilog_layout { /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ -/* Write Register 7' (ESCC Only) */ -#define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */ -#define AUTO_EOM_RST 2 /* Automatic EOM Reset */ -#define AUTOnRTS 4 /* Automatic /RTS pin deactivation */ -#define RxFIFO_LVL 8 /* Receive FIFO interrupt level */ -#define nDTRnREQ 0x10 /* /DTR/REQ timing */ -#define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */ -#define EXT_RD_EN 0x40 /* Extended read register enable */ - /* Write Register 8 (transmit buffer) */ /* Write Register 9 (Master interrupt control) */ @@ -145,7 +135,6 @@ struct zilog_layout { #define DLC 4 /* Disable Lower Chain */ #define MIE 8 /* Master Interrupt Enable */ #define STATHI 0x10 /* Status high */ -#define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */ #define NORESET 0 /* No reset on write to R9 */ #define CHRB 0x40 /* Reset channel B */ #define CHRA 0x80 /* Reset channel A */ @@ -198,9 +187,7 @@ struct zilog_layout { #define SNRZI 0xe0 /* Set NRZI mode */ /* Write Register 15 (external/status interrupt control) */ -#define WR7pEN 1 /* WR7' Enable (ESCC only) */ #define ZCIE 2 /* Zero count IE */ -#define FIFOEN 4 /* FIFO Enable (ESCC only) */ #define DCDIE 8 /* DCD IE */ #define SYNCIE 0x10 /* Sync/hunt IE */ #define CTSIE 0x20 /* CTS IE */ @@ -254,10 +241,6 @@ struct zilog_layout { #define CHATxIP 0x10 /* Channel A Tx IP */ #define CHARxIP 0x20 /* Channel A Rx IP */ -/* Read Register 6 (LSB frame byte count [Not on NMOS]) */ - -/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */ - /* Read Register 8 (receive data register) */ /* Read Register 10 (misc status bits) */ diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index 5e3f748f2693..07c587ec71be 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -6,7 +6,6 @@ # fully appropriate there, so it'd need some thought to do well. # menu "SPI support" - depends on HAS_IOMEM config SPI bool "SPI support" @@ -107,13 +106,6 @@ config SPI_IMX This enables using the Freescale iMX SPI controller in master mode. -config SPI_MPC52xx_PSC - tristate "Freescale MPC52xx PSC SPI controller" - depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL - help - This enables using the Freescale MPC52xx Programmable Serial - Controller in master SPI mode. - config SPI_MPC83xx tristate "Freescale MPC83xx SPI controller" depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL diff --git a/trunk/drivers/spi/Makefile b/trunk/drivers/spi/Makefile index 5788d867de84..624b6363f490 100644 --- a/trunk/drivers/spi/Makefile +++ b/trunk/drivers/spi/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o -obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o diff --git a/trunk/drivers/spi/atmel_spi.c b/trunk/drivers/spi/atmel_spi.c index 1d8a2f6bb8eb..66e7bc985797 100644 --- a/trunk/drivers/spi/atmel_spi.c +++ b/trunk/drivers/spi/atmel_spi.c @@ -22,7 +22,10 @@ #include #include #include + +#ifdef CONFIG_ARCH_AT91 #include +#endif #include "atmel_spi.h" @@ -549,8 +552,10 @@ static int __init atmel_spi_probe(struct platform_device *pdev) goto out_free_buffer; as->irq = irq; as->clk = clk; +#ifdef CONFIG_ARCH_AT91 if (!cpu_is_at91rm9200()) as->new_1 = 1; +#endif ret = request_irq(irq, atmel_spi_interrupt, 0, pdev->dev.bus_id, master); diff --git a/trunk/drivers/spi/mpc52xx_psc_spi.c b/trunk/drivers/spi/mpc52xx_psc_spi.c deleted file mode 100644 index 052359fc41ee..000000000000 --- a/trunk/drivers/spi/mpc52xx_psc_spi.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - * MPC52xx SPC in SPI mode driver. - * - * Maintainer: Dragos Carp - * - * Copyright (C) 2006 TOPTICA Photonics AG. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the 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 - -#if defined(CONFIG_PPC_MERGE) -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define MCLK 20000000 /* PSC port MClk in hz */ - -struct mpc52xx_psc_spi { - /* fsl_spi_platform data */ - void (*activate_cs)(u8, u8); - void (*deactivate_cs)(u8, u8); - u32 sysclk; - - /* driver internal data */ - struct mpc52xx_psc __iomem *psc; - unsigned int irq; - u8 bits_per_word; - u8 busy; - - struct workqueue_struct *workqueue; - struct work_struct work; - - struct list_head queue; - spinlock_t lock; - - struct completion done; -}; - -/* controller state */ -struct mpc52xx_psc_spi_cs { - int bits_per_word; - int speed_hz; -}; - -/* set clock freq, clock ramp, bits per work - * if t is NULL then reset the values to the default values - */ -static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi, - struct spi_transfer *t) -{ - struct mpc52xx_psc_spi_cs *cs = spi->controller_state; - - cs->speed_hz = (t && t->speed_hz) - ? t->speed_hz : spi->max_speed_hz; - cs->bits_per_word = (t && t->bits_per_word) - ? t->bits_per_word : spi->bits_per_word; - cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8; - return 0; -} - -static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) -{ - struct mpc52xx_psc_spi_cs *cs = spi->controller_state; - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - struct mpc52xx_psc __iomem *psc = mps->psc; - u32 sicr; - u16 ccr; - - sicr = in_be32(&psc->sicr); - - /* Set clock phase and polarity */ - if (spi->mode & SPI_CPHA) - sicr |= 0x00001000; - else - sicr &= ~0x00001000; - if (spi->mode & SPI_CPOL) - sicr |= 0x00002000; - else - sicr &= ~0x00002000; - - if (spi->mode & SPI_LSB_FIRST) - sicr |= 0x10000000; - else - sicr &= ~0x10000000; - out_be32(&psc->sicr, sicr); - - /* Set clock frequency and bits per word - * Because psc->ccr is defined as 16bit register instead of 32bit - * just set the lower byte of BitClkDiv - */ - ccr = in_be16(&psc->ccr); - ccr &= 0xFF00; - if (cs->speed_hz) - ccr |= (MCLK / cs->speed_hz - 1) & 0xFF; - else /* by default SPI Clk 1MHz */ - ccr |= (MCLK / 1000000 - 1) & 0xFF; - out_be16(&psc->ccr, ccr); - mps->bits_per_word = cs->bits_per_word; - - if (mps->activate_cs) - mps->activate_cs(spi->chip_select, - (spi->mode & SPI_CS_HIGH) ? 1 : 0); -} - -static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi) -{ - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - - if (mps->deactivate_cs) - mps->deactivate_cs(spi->chip_select, - (spi->mode & SPI_CS_HIGH) ? 1 : 0); -} - -#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1) -/* wake up when 80% fifo full */ -#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100) - -static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, - struct spi_transfer *t) -{ - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - struct mpc52xx_psc __iomem *psc = mps->psc; - unsigned rb = 0; /* number of bytes receieved */ - unsigned sb = 0; /* number of bytes sent */ - unsigned char *rx_buf = (unsigned char *)t->rx_buf; - unsigned char *tx_buf = (unsigned char *)t->tx_buf; - unsigned rfalarm; - unsigned send_at_once = MPC52xx_PSC_BUFSIZE; - unsigned recv_at_once; - unsigned bpw = mps->bits_per_word / 8; - - if (!t->tx_buf && !t->rx_buf && t->len) - return -EINVAL; - - /* enable transmiter/receiver */ - out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - while (rb < t->len) { - if (t->len - rb > MPC52xx_PSC_BUFSIZE) { - rfalarm = MPC52xx_PSC_RFALARM; - } else { - send_at_once = t->len - sb; - rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb); - } - - dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once); - if (tx_buf) { - for (; send_at_once; sb++, send_at_once--) { - /* set EOF flag */ - if (mps->bits_per_word - && (sb + 1) % bpw == 0) - out_8(&psc->ircr2, 0x01); - out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]); - } - } else { - for (; send_at_once; sb++, send_at_once--) { - /* set EOF flag */ - if (mps->bits_per_word - && ((sb + 1) % bpw) == 0) - out_8(&psc->ircr2, 0x01); - out_8(&psc->mpc52xx_psc_buffer_8, 0); - } - } - - - /* enable interupts and wait for wake up - * if just one byte is expected the Rx FIFO genererates no - * FFULL interrupt, so activate the RxRDY interrupt - */ - out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); - if (t->len - rb == 1) { - out_8(&psc->mode, 0); - } else { - out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); - out_be16(&psc->rfalarm, rfalarm); - } - out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY); - wait_for_completion(&mps->done); - recv_at_once = in_be16(&psc->rfnum); - dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once); - - send_at_once = recv_at_once; - if (rx_buf) { - for (; recv_at_once; rb++, recv_at_once--) - rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8); - } else { - for (; recv_at_once; rb++, recv_at_once--) - in_8(&psc->mpc52xx_psc_buffer_8); - } - } - /* disable transmiter/receiver */ - out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); - - return 0; -} - -static void mpc52xx_psc_spi_work(struct work_struct *work) -{ - struct mpc52xx_psc_spi *mps = - container_of(work, struct mpc52xx_psc_spi, work); - - spin_lock_irq(&mps->lock); - mps->busy = 1; - while (!list_empty(&mps->queue)) { - struct spi_message *m; - struct spi_device *spi; - struct spi_transfer *t = NULL; - unsigned cs_change; - int status; - - m = container_of(mps->queue.next, struct spi_message, queue); - list_del_init(&m->queue); - spin_unlock_irq(&mps->lock); - - spi = m->spi; - cs_change = 1; - status = 0; - list_for_each_entry (t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - status = mpc52xx_psc_spi_transfer_setup(spi, t); - if (status < 0) - break; - } - - if (cs_change) - mpc52xx_psc_spi_activate_cs(spi); - cs_change = t->cs_change; - - status = mpc52xx_psc_spi_transfer_rxtx(spi, t); - if (status) - break; - m->actual_length += t->len; - - if (t->delay_usecs) - udelay(t->delay_usecs); - - if (cs_change) - mpc52xx_psc_spi_deactivate_cs(spi); - } - - m->status = status; - m->complete(m->context); - - if (status || !cs_change) - mpc52xx_psc_spi_deactivate_cs(spi); - - mpc52xx_psc_spi_transfer_setup(spi, NULL); - - spin_lock_irq(&mps->lock); - } - mps->busy = 0; - spin_unlock_irq(&mps->lock); -} - -static int mpc52xx_psc_spi_setup(struct spi_device *spi) -{ - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - struct mpc52xx_psc_spi_cs *cs = spi->controller_state; - unsigned long flags; - - if (spi->bits_per_word%8) - return -EINVAL; - - if (!cs) { - cs = kzalloc(sizeof *cs, GFP_KERNEL); - if (!cs) - return -ENOMEM; - spi->controller_state = cs; - } - - cs->bits_per_word = spi->bits_per_word; - cs->speed_hz = spi->max_speed_hz; - - spin_lock_irqsave(&mps->lock, flags); - if (!mps->busy) - mpc52xx_psc_spi_deactivate_cs(spi); - spin_unlock_irqrestore(&mps->lock, flags); - - return 0; -} - -static int mpc52xx_psc_spi_transfer(struct spi_device *spi, - struct spi_message *m) -{ - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); - unsigned long flags; - - m->actual_length = 0; - m->status = -EINPROGRESS; - - spin_lock_irqsave(&mps->lock, flags); - list_add_tail(&m->queue, &mps->queue); - queue_work(mps->workqueue, &mps->work); - spin_unlock_irqrestore(&mps->lock, flags); - - return 0; -} - -static void mpc52xx_psc_spi_cleanup(struct spi_device *spi) -{ - kfree(spi->controller_state); -} - -static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) -{ - struct mpc52xx_cdm __iomem *cdm; - struct mpc52xx_gpio __iomem *gpio; - struct mpc52xx_psc __iomem *psc = mps->psc; - u32 ul; - u32 mclken_div; - int ret = 0; - -#if defined(CONFIG_PPC_MERGE) - cdm = mpc52xx_find_and_map("mpc52xx-cdm"); - gpio = mpc52xx_find_and_map("mpc52xx-gpio"); -#else - cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); - gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE); -#endif - if (!cdm || !gpio) { - printk(KERN_ERR "Error mapping CDM/GPIO\n"); - ret = -EFAULT; - goto unmap_regs; - } - - /* default sysclk is 512MHz */ - mclken_div = 0x8000 | - (((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF); - - switch (psc_id) { - case 1: - ul = in_be32(&gpio->port_config); - ul &= 0xFFFFFFF8; - ul |= 0x00000006; - out_be32(&gpio->port_config, ul); - out_be16(&cdm->mclken_div_psc1, mclken_div); - ul = in_be32(&cdm->clk_enables); - ul |= 0x00000020; - out_be32(&cdm->clk_enables, ul); - break; - case 2: - ul = in_be32(&gpio->port_config); - ul &= 0xFFFFFF8F; - ul |= 0x00000060; - out_be32(&gpio->port_config, ul); - out_be16(&cdm->mclken_div_psc2, mclken_div); - ul = in_be32(&cdm->clk_enables); - ul |= 0x00000040; - out_be32(&cdm->clk_enables, ul); - break; - case 3: - ul = in_be32(&gpio->port_config); - ul &= 0xFFFFF0FF; - ul |= 0x00000600; - out_be32(&gpio->port_config, ul); - out_be16(&cdm->mclken_div_psc3, mclken_div); - ul = in_be32(&cdm->clk_enables); - ul |= 0x00000080; - out_be32(&cdm->clk_enables, ul); - break; - case 6: - ul = in_be32(&gpio->port_config); - ul &= 0xFF8FFFFF; - ul |= 0x00700000; - out_be32(&gpio->port_config, ul); - out_be16(&cdm->mclken_div_psc6, mclken_div); - ul = in_be32(&cdm->clk_enables); - ul |= 0x00000010; - out_be32(&cdm->clk_enables, ul); - break; - default: - ret = -EINVAL; - goto unmap_regs; - } - - /* Reset the PSC into a known state */ - out_8(&psc->command, MPC52xx_PSC_RST_RX); - out_8(&psc->command, MPC52xx_PSC_RST_TX); - out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); - - /* Disable interrupts, interrupts are based on alarm level */ - out_be16(&psc->mpc52xx_psc_imr, 0); - out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); - out_8(&psc->rfcntl, 0); - out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); - - /* Configure 8bit codec mode as a SPI master and use EOF flags */ - /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */ - out_be32(&psc->sicr, 0x0180C800); - out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */ - - /* Set 2ms DTL delay */ - out_8(&psc->ctur, 0x00); - out_8(&psc->ctlr, 0x84); - - mps->bits_per_word = 8; - -unmap_regs: - if (cdm) - iounmap(cdm); - if (gpio) - iounmap(gpio); - - return ret; -} - -static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id) -{ - struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id; - struct mpc52xx_psc __iomem *psc = mps->psc; - - /* disable interrupt and wake up the work queue */ - if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) { - out_be16(&psc->mpc52xx_psc_imr, 0); - complete(&mps->done); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* bus_num is used only for the case dev->platform_data == NULL */ -static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, - u32 size, unsigned int irq, s16 bus_num) -{ - struct fsl_spi_platform_data *pdata = dev->platform_data; - struct mpc52xx_psc_spi *mps; - struct spi_master *master; - int ret; - - if (pdata == NULL) - return -ENODEV; - - master = spi_alloc_master(dev, sizeof *mps); - if (master == NULL) - return -ENOMEM; - - dev_set_drvdata(dev, master); - mps = spi_master_get_devdata(master); - - mps->irq = irq; - if (pdata == NULL) { - dev_warn(dev, "probe called without platform data, no " - "(de)activate_cs function will be called\n"); - mps->activate_cs = NULL; - mps->deactivate_cs = NULL; - mps->sysclk = 0; - master->bus_num = bus_num; - master->num_chipselect = 255; - } else { - mps->activate_cs = pdata->activate_cs; - mps->deactivate_cs = pdata->deactivate_cs; - mps->sysclk = pdata->sysclk; - master->bus_num = pdata->bus_num; - master->num_chipselect = pdata->max_chipselect; - } - master->setup = mpc52xx_psc_spi_setup; - master->transfer = mpc52xx_psc_spi_transfer; - master->cleanup = mpc52xx_psc_spi_cleanup; - - mps->psc = ioremap(regaddr, size); - if (!mps->psc) { - dev_err(dev, "could not ioremap I/O port range\n"); - ret = -EFAULT; - goto free_master; - } - - ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi", - mps); - if (ret) - goto free_master; - - ret = mpc52xx_psc_spi_port_config(master->bus_num, mps); - if (ret < 0) - goto free_irq; - - spin_lock_init(&mps->lock); - init_completion(&mps->done); - INIT_WORK(&mps->work, mpc52xx_psc_spi_work); - INIT_LIST_HEAD(&mps->queue); - - mps->workqueue = create_singlethread_workqueue( - master->cdev.dev->bus_id); - if (mps->workqueue == NULL) { - ret = -EBUSY; - goto free_irq; - } - - ret = spi_register_master(master); - if (ret < 0) - goto unreg_master; - - return ret; - -unreg_master: - destroy_workqueue(mps->workqueue); -free_irq: - free_irq(mps->irq, mps); -free_master: - if (mps->psc) - iounmap(mps->psc); - spi_master_put(master); - - return ret; -} - -static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) -{ - struct spi_master *master = dev_get_drvdata(dev); - struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); - - flush_workqueue(mps->workqueue); - destroy_workqueue(mps->workqueue); - spi_unregister_master(master); - free_irq(mps->irq, mps); - if (mps->psc) - iounmap(mps->psc); - - return 0; -} - -#if !defined(CONFIG_PPC_MERGE) -static int __init mpc52xx_psc_spi_probe(struct platform_device *dev) -{ - switch(dev->id) { - case 1: - case 2: - case 3: - case 6: - return mpc52xx_psc_spi_do_probe(&dev->dev, - MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)), - MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id); - default: - return -EINVAL; - } -} - -static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev) -{ - return mpc52xx_psc_spi_do_remove(&dev->dev); -} - -static struct platform_driver mpc52xx_psc_spi_platform_driver = { - .remove = __exit_p(mpc52xx_psc_spi_remove), - .driver = { - .name = "mpc52xx-psc-spi", - .owner = THIS_MODULE, - }, -}; - -static int __init mpc52xx_psc_spi_init(void) -{ - return platform_driver_probe(&mpc52xx_psc_spi_platform_driver, - mpc52xx_psc_spi_probe); -} -module_init(mpc52xx_psc_spi_init); - -static void __exit mpc52xx_psc_spi_exit(void) -{ - platform_driver_unregister(&mpc52xx_psc_spi_platform_driver); -} -module_exit(mpc52xx_psc_spi_exit); - -#else /* defined(CONFIG_PPC_MERGE) */ - -static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, - const struct of_device_id *match) -{ - const u32 *regaddr_p; - u64 regaddr64, size64; - s16 id = -1; - - regaddr_p = of_get_address(op->node, 0, &size64, NULL); - if (!regaddr_p) { - printk(KERN_ERR "Invalid PSC address\n"); - return -EINVAL; - } - regaddr64 = of_translate_address(op->node, regaddr_p); - - if (op->dev.platform_data == NULL) { - struct device_node *np; - int i = 0; - - for_each_node_by_type(np, "spi") { - if (of_find_device_by_node(np) == op) { - id = i; - break; - } - i++; - } - } - - return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64, - irq_of_parse_and_map(op->node, 0), id); -} - -static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) -{ - return mpc52xx_psc_spi_do_remove(&op->dev); -} - -static struct of_device_id mpc52xx_psc_spi_of_match[] = { - { .type = "spi", .compatible = "mpc52xx-psc-spi", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match); - -static struct of_platform_driver mpc52xx_psc_spi_of_driver = { - .owner = THIS_MODULE, - .name = "mpc52xx-psc-spi", - .match_table = mpc52xx_psc_spi_of_match, - .probe = mpc52xx_psc_spi_of_probe, - .remove = __exit_p(mpc52xx_psc_spi_of_remove), - .driver = { - .name = "mpc52xx-psc-spi", - .owner = THIS_MODULE, - }, -}; - -static int __init mpc52xx_psc_spi_init(void) -{ - return of_register_platform_driver(&mpc52xx_psc_spi_of_driver); -} -module_init(mpc52xx_psc_spi_init); - -static void __exit mpc52xx_psc_spi_exit(void) -{ - of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver); -} -module_exit(mpc52xx_psc_spi_exit); - -#endif /* defined(CONFIG_PPC_MERGE) */ - -MODULE_AUTHOR("Dragos Carp"); -MODULE_DESCRIPTION("MPC52xx PSC SPI Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/telephony/Kconfig b/trunk/drivers/telephony/Kconfig index dd1d6a53f3c0..7625b1816baf 100644 --- a/trunk/drivers/telephony/Kconfig +++ b/trunk/drivers/telephony/Kconfig @@ -3,7 +3,6 @@ # menu "Telephony Support" - depends on HAS_IOMEM config PHONE tristate "Linux telephony support" diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index 15499b7e33f4..b847bbc8b0e1 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -3,7 +3,6 @@ # menu "USB support" - depends on HAS_IOMEM # Host-side USB depends on having a host controller # NOTE: dummy_hcd is always an option, but it's ignored here ... @@ -88,6 +87,8 @@ source "drivers/usb/storage/Kconfig" source "drivers/usb/image/Kconfig" +source "drivers/usb/net/Kconfig" + source "drivers/usb/mon/Kconfig" comment "USB port drivers" diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index 72464b586990..0ef090b1b37c 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -23,6 +23,13 @@ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB) += storage/ +obj-$(CONFIG_USB_CATC) += net/ +obj-$(CONFIG_USB_KAWETH) += net/ +obj-$(CONFIG_USB_PEGASUS) += net/ +obj-$(CONFIG_USB_RTL8150) += net/ +obj-$(CONFIG_USB_USBNET) += net/ +obj-$(CONFIG_USB_ZD1201) += net/ + obj-$(CONFIG_USB_MDC800) += image/ obj-$(CONFIG_USB_MICROTEK) += image/ diff --git a/trunk/drivers/usb/atm/usbatm.c b/trunk/drivers/usb/atm/usbatm.c index 11e9b15ca45a..b082d95bbbaa 100644 --- a/trunk/drivers/usb/atm/usbatm.c +++ b/trunk/drivers/usb/atm/usbatm.c @@ -1033,7 +1033,7 @@ static int usbatm_do_heavy_init(void *arg) static int usbatm_heavy_init(struct usbatm_data *instance) { - int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES); + int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL); if (ret < 0) { usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); diff --git a/trunk/drivers/usb/misc/auerswald.c b/trunk/drivers/usb/misc/auerswald.c index 88fb56d5db8f..b5332e679c46 100644 --- a/trunk/drivers/usb/misc/auerswald.c +++ b/trunk/drivers/usb/misc/auerswald.c @@ -1307,7 +1307,7 @@ static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp) } -/* remove a service from the device +/* remove a service from the the device scp->id must be set! */ static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp) { diff --git a/trunk/drivers/net/usb/Kconfig b/trunk/drivers/usb/net/Kconfig similarity index 100% rename from trunk/drivers/net/usb/Kconfig rename to trunk/drivers/usb/net/Kconfig diff --git a/trunk/drivers/net/usb/Makefile b/trunk/drivers/usb/net/Makefile similarity index 100% rename from trunk/drivers/net/usb/Makefile rename to trunk/drivers/usb/net/Makefile diff --git a/trunk/drivers/net/usb/asix.c b/trunk/drivers/usb/net/asix.c similarity index 100% rename from trunk/drivers/net/usb/asix.c rename to trunk/drivers/usb/net/asix.c diff --git a/trunk/drivers/net/usb/catc.c b/trunk/drivers/usb/net/catc.c similarity index 100% rename from trunk/drivers/net/usb/catc.c rename to trunk/drivers/usb/net/catc.c diff --git a/trunk/drivers/net/usb/cdc_ether.c b/trunk/drivers/usb/net/cdc_ether.c similarity index 100% rename from trunk/drivers/net/usb/cdc_ether.c rename to trunk/drivers/usb/net/cdc_ether.c diff --git a/trunk/drivers/net/usb/cdc_subset.c b/trunk/drivers/usb/net/cdc_subset.c similarity index 100% rename from trunk/drivers/net/usb/cdc_subset.c rename to trunk/drivers/usb/net/cdc_subset.c diff --git a/trunk/drivers/net/usb/dm9601.c b/trunk/drivers/usb/net/dm9601.c similarity index 100% rename from trunk/drivers/net/usb/dm9601.c rename to trunk/drivers/usb/net/dm9601.c diff --git a/trunk/drivers/net/usb/gl620a.c b/trunk/drivers/usb/net/gl620a.c similarity index 100% rename from trunk/drivers/net/usb/gl620a.c rename to trunk/drivers/usb/net/gl620a.c diff --git a/trunk/drivers/net/usb/kaweth.c b/trunk/drivers/usb/net/kaweth.c similarity index 100% rename from trunk/drivers/net/usb/kaweth.c rename to trunk/drivers/usb/net/kaweth.c diff --git a/trunk/drivers/net/usb/kawethfw.h b/trunk/drivers/usb/net/kawethfw.h similarity index 100% rename from trunk/drivers/net/usb/kawethfw.h rename to trunk/drivers/usb/net/kawethfw.h diff --git a/trunk/drivers/net/usb/mcs7830.c b/trunk/drivers/usb/net/mcs7830.c similarity index 100% rename from trunk/drivers/net/usb/mcs7830.c rename to trunk/drivers/usb/net/mcs7830.c diff --git a/trunk/drivers/net/usb/net1080.c b/trunk/drivers/usb/net/net1080.c similarity index 100% rename from trunk/drivers/net/usb/net1080.c rename to trunk/drivers/usb/net/net1080.c diff --git a/trunk/drivers/net/usb/pegasus.c b/trunk/drivers/usb/net/pegasus.c similarity index 100% rename from trunk/drivers/net/usb/pegasus.c rename to trunk/drivers/usb/net/pegasus.c diff --git a/trunk/drivers/net/usb/pegasus.h b/trunk/drivers/usb/net/pegasus.h similarity index 100% rename from trunk/drivers/net/usb/pegasus.h rename to trunk/drivers/usb/net/pegasus.h diff --git a/trunk/drivers/net/usb/plusb.c b/trunk/drivers/usb/net/plusb.c similarity index 100% rename from trunk/drivers/net/usb/plusb.c rename to trunk/drivers/usb/net/plusb.c diff --git a/trunk/drivers/net/usb/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c similarity index 100% rename from trunk/drivers/net/usb/rndis_host.c rename to trunk/drivers/usb/net/rndis_host.c diff --git a/trunk/drivers/net/usb/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c similarity index 100% rename from trunk/drivers/net/usb/rtl8150.c rename to trunk/drivers/usb/net/rtl8150.c diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/usb/net/usbnet.c similarity index 100% rename from trunk/drivers/net/usb/usbnet.c rename to trunk/drivers/usb/net/usbnet.c diff --git a/trunk/drivers/net/usb/usbnet.h b/trunk/drivers/usb/net/usbnet.h similarity index 99% rename from trunk/drivers/net/usb/usbnet.h rename to trunk/drivers/usb/net/usbnet.h index 82db5a8e528e..cbb53e065d6c 100644 --- a/trunk/drivers/net/usb/usbnet.h +++ b/trunk/drivers/usb/net/usbnet.h @@ -129,7 +129,7 @@ extern void usbnet_disconnect(struct usb_interface *); /* Drivers that reuse some of the standard USB CDC infrastructure - * (notably, using multiple interfaces according to the CDC + * (notably, using multiple interfaces according to the the CDC * union descriptor) get some helper code. */ struct cdc_state { diff --git a/trunk/drivers/net/usb/zaurus.c b/trunk/drivers/usb/net/zaurus.c similarity index 100% rename from trunk/drivers/net/usb/zaurus.c rename to trunk/drivers/usb/net/zaurus.c diff --git a/trunk/drivers/usb/serial/Kconfig b/trunk/drivers/usb/serial/Kconfig index 3efe67092f15..ba5d1dc03036 100644 --- a/trunk/drivers/usb/serial/Kconfig +++ b/trunk/drivers/usb/serial/Kconfig @@ -558,7 +558,7 @@ config USB_SERIAL_DEBUG tristate "USB Debugging Device" depends on USB_SERIAL help - Say Y here if you have a USB debugging device used to receive + Say Y here if you have a USB debugging device used to recieve debugging data from another machine. The most common of these devices is the NetChip TurboCONNECT device. diff --git a/trunk/drivers/usb/serial/aircable.c b/trunk/drivers/usb/serial/aircable.c index fbc8c27d5d99..b675735bfbee 100644 --- a/trunk/drivers/usb/serial/aircable.c +++ b/trunk/drivers/usb/serial/aircable.c @@ -9,7 +9,7 @@ * The device works as an standard CDC device, it has 2 interfaces, the first * one is for firmware access and the second is the serial one. * The protocol is very simply, there are two posibilities reading or writing. - * When writing the first urb must have a Header that starts with 0x20 0x29 the + * When writting the first urb must have a Header that starts with 0x20 0x29 the * next two bytes must say how much data will be sended. * When reading the process is almost equal except that the header starts with * 0x00 0x20. @@ -18,7 +18,7 @@ * buffer: The First and Second byte is used for a Header, the Third and Fourth * tells the device the amount of information the package holds. * Packages are 60 bytes long Header Stuff. - * When writing to the device the first two bytes of the header are 0x20 0x29 + * When writting to the device the first two bytes of the header are 0x20 0x29 * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange * situation, when too much data arrives to the device because it sends the data * but with out the header. I will use a simply hack to override this situation, diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index 4807f960150b..18f74ac76565 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -2465,7 +2465,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ((edge_serial->is_epic) && (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && (regNum == MCR))) { - dbg("SendCmdWriteUartReg - Not writing to MCR Register"); + dbg("SendCmdWriteUartReg - Not writting to MCR Register"); return 0; } @@ -2473,7 +2473,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ((edge_serial->is_epic) && (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && (regNum == LCR))) { - dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); + dbg ("SendCmdWriteUartReg - Not writting to LCR Register"); return 0; } diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index eebcb708cff1..1132ba5ff391 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -3,7 +3,6 @@ # menu "Graphics support" - depends on HAS_IOMEM source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" @@ -748,22 +747,6 @@ config FB_S1D13XXX working with S1D13806). Product specs at -config FB_ATMEL - tristate "AT91/AT32 LCD Controller support" - depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This enables support for the AT91/AT32 LCD Controller. - -config FB_INTSRAM - bool "Frame Buffer in internal SRAM" - depends on FB_ATMEL && ARCH_AT91SAM9261 - help - Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want - to let frame buffer in external SDRAM. - config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI @@ -796,15 +779,6 @@ config FB_NVIDIA_I2C independently validate video mode parameters, you should say Y here. -config FB_NVIDIA_DEBUG - bool "Lots of debug output" - depends on FB_NVIDIA - default n - help - Say Y here if you want the nVidia driver to output all sorts - of debugging information to provide to the maintainer when - something goes wrong. - config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" depends on FB_NVIDIA @@ -844,7 +818,7 @@ config FB_RIVA_I2C here. config FB_RIVA_DEBUG - bool "Lots of debug output" + bool "Lots of debug output from Riva(nVidia) driver" depends on FB_RIVA default n help @@ -1374,20 +1348,6 @@ config FB_VOODOO1 Please read the for supported options and other important info support. -config FB_VT8623 - tristate "VIA VT8623 support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for CastleRock integrated graphics core in the - VIA VT8623 [Apollo CLE266] chipset. - config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI && X86_32 && !64BIT @@ -1441,26 +1401,9 @@ config FB_TRIDENT_ACCEL This will compile the Trident frame buffer device with acceleration functions. -config FB_ARK - tristate "ARK 2000PV support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for PCI graphics boards with ARK 2000PV chip - and ICS 5342 RAMDAC. - config FB_PM3 - tristate "Permedia3 support (EXPERIMENTAL)" - depends on FB && PCI && EXPERIMENTAL - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + tristate "Permedia3 support" + depends on FB && PCI && BROKEN help This is the frame buffer device driver for the 3DLabs Permedia3 chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index bd8b05229500..a916c204274f 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -54,12 +54,10 @@ obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o obj-$(CONFIG_FB_CT65550) += chipsfb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o obj-$(CONFIG_FB_FM2) += fm2fb.o -obj-$(CONFIG_FB_VT8623) += vt8623fb.o obj-$(CONFIG_FB_CYBLA) += cyblafb.o obj-$(CONFIG_FB_TRIDENT) += tridentfb.o obj-$(CONFIG_FB_LE80578) += vermilion/ obj-$(CONFIG_FB_S3) += s3fb.o -obj-$(CONFIG_FB_ARK) += arkfb.o obj-$(CONFIG_FB_STI) += stifb.o obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o @@ -87,7 +85,6 @@ obj-$(CONFIG_FB_G364) += g364fb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_HIT) += hitfb.o obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o -obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o diff --git a/trunk/drivers/video/arkfb.c b/trunk/drivers/video/arkfb.c deleted file mode 100644 index ba6fede5c466..000000000000 --- a/trunk/drivers/video/arkfb.c +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV - * with ICS 5342 dac (it is easy to add support for different dacs). - * - * Copyright (c) 2007 Ondrej Zajicek - * - * 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. - * - * Code is based on s3fb - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Why should fb driver call console functions? because acquire_console_sem() */ -#include