Merge branch 'fix/misc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Mon, 21 Dec 2009 11:05:40 +0000 (12:05 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 21 Dec 2009 11:05:40 +0000 (12:05 +0100)
636 files changed:
.gitignore
Documentation/cpu-hotplug.txt
Documentation/dontdiff
Documentation/hwmon/k10temp [new file with mode: 0644]
Documentation/kbuild/kbuild.txt
Documentation/kbuild/kconfig.txt
Kbuild
MAINTAINERS
Makefile
arch/alpha/boot/bootp.c
arch/alpha/boot/bootpz.c
arch/alpha/boot/main.c
arch/alpha/include/asm/asm-offsets.h [new file with mode: 0644]
arch/alpha/include/asm/fcntl.h
arch/arm/Makefile
arch/arm/common/dmabounce.c
arch/arm/include/asm/asm-offsets.h [new file with mode: 0644]
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/mach-types.h [new file with mode: 0644]
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/Makefile
arch/arm/mach-kirkwood/netspace_v2-setup.c [new file with mode: 0644]
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/devices.c
arch/arm/mach-s3c2410/include/mach/spi.h
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/flush.c
arch/arm/mm/highmem.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-syms.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/tools/Makefile
arch/arm/tools/gen-mach-types
arch/arm/tools/mach-types
arch/avr32/include/asm/asm-offsets.h [new file with mode: 0644]
arch/blackfin/include/asm/asm-offsets.h [new file with mode: 0644]
arch/cris/arch-v32/kernel/head.S
arch/cris/include/asm/asm-offsets.h [new file with mode: 0644]
arch/cris/kernel/asm-offsets.c
arch/cris/kernel/vmlinux.lds.S
arch/frv/include/asm/asm-offsets.h [new file with mode: 0644]
arch/frv/kernel/setup.c
arch/h8300/include/asm/asm-offsets.h [new file with mode: 0644]
arch/ia64/Makefile
arch/ia64/include/asm/asm-offsets.h [new file with mode: 0644]
arch/ia64/include/asm/irq.h
arch/ia64/kernel/Makefile
arch/ia64/kvm/asm-offsets.c
arch/m68k/include/asm/asm-offsets.h [new file with mode: 0644]
arch/m68k/kernel/head.S
arch/microblaze/include/asm/asm-offsets.h [new file with mode: 0644]
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/Makefile
arch/mips/ar7/platform.c
arch/mips/basler/excite/Kconfig [deleted file]
arch/mips/basler/excite/Makefile [deleted file]
arch/mips/basler/excite/excite_device.c [deleted file]
arch/mips/basler/excite/excite_iodev.c [deleted file]
arch/mips/basler/excite/excite_iodev.h [deleted file]
arch/mips/basler/excite/excite_irq.c [deleted file]
arch/mips/basler/excite/excite_procfs.c [deleted file]
arch/mips/basler/excite/excite_prom.c [deleted file]
arch/mips/basler/excite/excite_setup.c [deleted file]
arch/mips/bcm47xx/prom.c
arch/mips/boot/Makefile
arch/mips/boot/addinitrd.c [deleted file]
arch/mips/boot/compressed/Makefile [new file with mode: 0644]
arch/mips/boot/compressed/dbg.c [new file with mode: 0644]
arch/mips/boot/compressed/decompress.c [new file with mode: 0644]
arch/mips/boot/compressed/dummy.c [new file with mode: 0644]
arch/mips/boot/compressed/head.S [new file with mode: 0644]
arch/mips/boot/compressed/ld.script [new file with mode: 0644]
arch/mips/boot/compressed/uart-16550.c [new file with mode: 0644]
arch/mips/cavium-octeon/Makefile
arch/mips/cavium-octeon/cpu.c [new file with mode: 0644]
arch/mips/cavium-octeon/octeon-platform.c
arch/mips/configs/ar7_defconfig
arch/mips/configs/bcm47xx_defconfig
arch/mips/configs/bcm63xx_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/cavium-octeon_defconfig
arch/mips/configs/cobalt_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1100_defconfig
arch/mips/configs/db1200_defconfig
arch/mips/configs/db1500_defconfig
arch/mips/configs/db1550_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/excite_defconfig [deleted file]
arch/mips/configs/fuloong2e_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip28_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/jmr3927_defconfig
arch/mips/configs/lasat_defconfig
arch/mips/configs/lemote2f_defconfig [new file with mode: 0644]
arch/mips/configs/malta_defconfig
arch/mips/configs/markeins_defconfig
arch/mips/configs/mipssim_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/msp71xx_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/configs/pb1100_defconfig
arch/mips/configs/pb1500_defconfig
arch/mips/configs/pb1550_defconfig
arch/mips/configs/pnx8335-stb225_defconfig
arch/mips/configs/pnx8550-jbs_defconfig
arch/mips/configs/pnx8550-stb810_defconfig
arch/mips/configs/powertv_defconfig [new file with mode: 0644]
arch/mips/configs/rb532_defconfig
arch/mips/configs/rbtx49xx_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/tb0219_defconfig
arch/mips/configs/tb0226_defconfig
arch/mips/configs/tb0287_defconfig
arch/mips/configs/workpad_defconfig
arch/mips/configs/wrppmc_defconfig
arch/mips/configs/yosemite_defconfig
arch/mips/fw/arc/cmdline.c
arch/mips/include/asm/asm-offsets.h [new file with mode: 0644]
arch/mips/include/asm/bootinfo.h
arch/mips/include/asm/clock.h [new file with mode: 0644]
arch/mips/include/asm/cop2.h [new file with mode: 0644]
arch/mips/include/asm/cpu.h
arch/mips/include/asm/fcntl.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/fpu_emulator.h
arch/mips/include/asm/ftrace.h
arch/mips/include/asm/irq.h
arch/mips/include/asm/mach-excite/cpu-feature-overrides.h [deleted file]
arch/mips/include/asm/mach-excite/excite.h [deleted file]
arch/mips/include/asm/mach-excite/excite_fpga.h [deleted file]
arch/mips/include/asm/mach-excite/excite_nandflash.h [deleted file]
arch/mips/include/asm/mach-excite/rm9k_eth.h [deleted file]
arch/mips/include/asm/mach-excite/rm9k_wdt.h [deleted file]
arch/mips/include/asm/mach-excite/rm9k_xicap.h [deleted file]
arch/mips/include/asm/mach-loongson/cs5536/cs5536.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/dma-coherence.h
arch/mips/include/asm/mach-loongson/loongson.h
arch/mips/include/asm/mach-loongson/machine.h
arch/mips/include/asm/mach-loongson/mem.h
arch/mips/include/asm/mach-loongson/pci.h
arch/mips/include/asm/mach-powertv/asic.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/asic_regs.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/dma-coherence.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/interrupts.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/ioremap.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/powertv-clock.h [new file with mode: 0644]
arch/mips/include/asm/mach-powertv/war.h [moved from arch/mips/include/asm/mach-excite/war.h with 56% similarity]
arch/mips/include/asm/mips-boards/bonito64.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/octeon/cvmx-agl-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-mixx-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-smix-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/octeon.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/sgialib.h
arch/mips/include/asm/stackframe.h
arch/mips/kernel/Makefile
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/cpufreq/Kconfig [new file with mode: 0644]
arch/mips/kernel/cpufreq/Makefile [new file with mode: 0644]
arch/mips/kernel/cpufreq/loongson2_clock.c [new file with mode: 0644]
arch/mips/kernel/cpufreq/loongson2_cpufreq.c [new file with mode: 0644]
arch/mips/kernel/csrc-powertv.c [new file with mode: 0644]
arch/mips/kernel/ftrace.c [new file with mode: 0644]
arch/mips/kernel/irq.c
arch/mips/kernel/mcount.S [new file with mode: 0644]
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/lasat/picvue_proc.c
arch/mips/lasat/prom.c
arch/mips/lasat/sysctl.c
arch/mips/loongson/Kconfig
arch/mips/loongson/Makefile
arch/mips/loongson/common/Makefile
arch/mips/loongson/common/bonito-irq.c
arch/mips/loongson/common/cmdline.c
arch/mips/loongson/common/cs5536/Makefile [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_acc.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_ehci.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_ide.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_isa.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_mfgpt.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_ohci.c [new file with mode: 0644]
arch/mips/loongson/common/cs5536/cs5536_pci.c [new file with mode: 0644]
arch/mips/loongson/common/early_printk.c
arch/mips/loongson/common/env.c
arch/mips/loongson/common/init.c
arch/mips/loongson/common/irq.c
arch/mips/loongson/common/machtype.c
arch/mips/loongson/common/mem.c
arch/mips/loongson/common/pci.c
arch/mips/loongson/common/platform.c [new file with mode: 0644]
arch/mips/loongson/common/pm.c [new file with mode: 0644]
arch/mips/loongson/common/reset.c
arch/mips/loongson/common/serial.c [new file with mode: 0644]
arch/mips/loongson/common/time.c
arch/mips/loongson/common/uart_base.c [new file with mode: 0644]
arch/mips/loongson/fuloong-2e/irq.c
arch/mips/loongson/fuloong-2e/reset.c
arch/mips/loongson/lemote-2f/Makefile [new file with mode: 0644]
arch/mips/loongson/lemote-2f/ec_kb3310b.c [new file with mode: 0644]
arch/mips/loongson/lemote-2f/ec_kb3310b.h [new file with mode: 0644]
arch/mips/loongson/lemote-2f/irq.c [new file with mode: 0644]
arch/mips/loongson/lemote-2f/pm.c [new file with mode: 0644]
arch/mips/loongson/lemote-2f/reset.c [new file with mode: 0644]
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dsemul.c
arch/mips/mipssim/Makefile
arch/mips/mipssim/sim_setup.c
arch/mips/mm/cerr-sb1.c
arch/mips/mm/init.c
arch/mips/mm/tlbex.c
arch/mips/mm/uasm.c
arch/mips/mm/uasm.h
arch/mips/mti-malta/malta-memory.c
arch/mips/nxp/pnx833x/common/interrupts.c
arch/mips/oprofile/op_model_loongson2.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-excite.c [deleted file]
arch/mips/pci/fixup-fuloong2e.c
arch/mips/pci/fixup-lemote2f.c [new file with mode: 0644]
arch/mips/pci/ops-bonito64.c
arch/mips/pci/ops-loongson2.c [new file with mode: 0644]
arch/mips/pci/pci-excite.c [deleted file]
arch/mips/powertv/Kconfig [new file with mode: 0644]
arch/mips/powertv/Makefile [new file with mode: 0644]
arch/mips/powertv/asic/Kconfig [new file with mode: 0644]
arch/mips/powertv/asic/Makefile [new file with mode: 0644]
arch/mips/powertv/asic/asic-calliope.c [new file with mode: 0644]
arch/mips/powertv/asic/asic-cronus.c [new file with mode: 0644]
arch/mips/powertv/asic/asic-zeus.c [new file with mode: 0644]
arch/mips/powertv/asic/asic_devices.c [new file with mode: 0644]
arch/mips/powertv/asic/asic_int.c [new file with mode: 0644]
arch/mips/powertv/asic/irq_asic.c [new file with mode: 0644]
arch/mips/powertv/asic/prealloc-calliope.c [new file with mode: 0644]
arch/mips/powertv/asic/prealloc-cronus.c [new file with mode: 0644]
arch/mips/powertv/asic/prealloc-cronuslite.c [new file with mode: 0644]
arch/mips/powertv/asic/prealloc-zeus.c [new file with mode: 0644]
arch/mips/powertv/cmdline.c [new file with mode: 0644]
arch/mips/powertv/init.c [new file with mode: 0644]
arch/mips/powertv/init.h [new file with mode: 0644]
arch/mips/powertv/memory.c [new file with mode: 0644]
arch/mips/powertv/pci/Makefile [new file with mode: 0644]
arch/mips/powertv/pci/fixup-powertv.c [new file with mode: 0644]
arch/mips/powertv/pci/powertv-pci.h [new file with mode: 0644]
arch/mips/powertv/powertv-clock.h [new file with mode: 0644]
arch/mips/powertv/powertv_setup.c [new file with mode: 0644]
arch/mips/powertv/reset.c [new file with mode: 0644]
arch/mips/powertv/reset.h [new file with mode: 0644]
arch/mips/powertv/time.c [moved from arch/mips/mipssim/sim_cmdline.c with 60% similarity]
arch/mips/rb532/prom.c
arch/mips/sgi-ip22/ip22-eisa.c
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip22/ip22-setup.c
arch/mips/sgi-ip22/ip22-time.c
arch/mips/sgi-ip32/ip32-setup.c
arch/mips/sibyte/common/cfe.c
arch/mips/sni/a20r.c
arch/mips/sni/pcimt.c
arch/mips/sni/pcit.c
arch/mips/sni/rm200.c
arch/mips/sni/setup.c
arch/mips/txx9/generic/setup.c
arch/mn10300/include/asm/asm-offsets.h [new file with mode: 0644]
arch/parisc/include/asm/asm-offsets.h [new file with mode: 0644]
arch/powerpc/include/asm/asm-offsets.h [new file with mode: 0644]
arch/powerpc/platforms/52xx/efika.c
arch/powerpc/platforms/amigaone/setup.c
arch/powerpc/platforms/cell/spufs/Makefile
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/powermac/bootx_init.c
arch/s390/include/asm/asm-offsets.h [new file with mode: 0644]
arch/score/include/asm/asm-offsets.h [new file with mode: 0644]
arch/score/include/asm/cacheflush.h
arch/score/include/asm/delay.h
arch/score/include/asm/page.h
arch/score/kernel/setup.c
arch/score/mm/cache.c
arch/score/mm/init.c
arch/sh/Makefile
arch/sh/drivers/pci/fixups-rts7751r2d.c
arch/sh/include/asm/.gitignore [deleted file]
arch/sh/include/asm/asm-offsets.h [new file with mode: 0644]
arch/sh/include/asm/machvec.h
arch/sh/tools/Makefile
arch/sh/tools/gen-mach-types
arch/sparc/include/asm/asm-offsets.h [new file with mode: 0644]
arch/sparc/include/asm/fcntl.h
arch/um/Makefile
arch/um/include/asm/asm-offsets.h [new file with mode: 0644]
arch/x86/boot/header.S
arch/x86/boot/version.c
arch/x86/include/asm/asm-offsets.h [new file with mode: 0644]
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
arch/x86/kernel/ptrace.c
arch/xtensa/include/asm/asm-offsets.h [new file with mode: 0644]
drivers/accessibility/braille/braille_console.c
drivers/hid/hid-lg.h
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/k10temp.c [new file with mode: 0644]
drivers/hwmon/lis3lv02d_i2c.c [new file with mode: 0644]
drivers/hwmon/sht15.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/via-cputemp.c [new file with mode: 0644]
drivers/hwmon/w83627hf.c
drivers/idle/i7300_idle.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-adp5520.c [new file with mode: 0644]
drivers/leds/leds-alix2.c
drivers/leds/leds-cobalt-qube.c
drivers/leds/leds-cobalt-raq.c
drivers/leds/leds-lt3593.c [new file with mode: 0644]
drivers/leds/leds-pwm.c
drivers/leds/leds-regulator.c [new file with mode: 0644]
drivers/leds/leds-ss4200.c [new file with mode: 0644]
drivers/message/fusion/mptbase.c
drivers/misc/Kconfig
drivers/misc/enclosure.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/sdhci-of-core.c [moved from drivers/mmc/host/sdhci-of.c with 58% similarity]
drivers/mmc/host/sdhci-of-esdhc.c [new file with mode: 0644]
drivers/mmc/host/sdhci-of-hlwd.c [new file with mode: 0644]
drivers/mmc/host/sdhci-of.h [new file with mode: 0644]
drivers/mmc/host/sdhci.h
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/excite_nandflash.c [deleted file]
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/octeon/Kconfig [new file with mode: 0644]
drivers/net/octeon/Makefile [new file with mode: 0644]
drivers/net/octeon/octeon_mgmt.c [new file with mode: 0644]
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/mdio-octeon.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/pcmcia/pxa2xx_base.c
drivers/platform/x86/compal-laptop.c
drivers/regulator/88pm8607.c [new file with mode: 0644]
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/ab3100.c
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/lp3971.c
drivers/regulator/max8660.c [new file with mode: 0644]
drivers/regulator/mc13783-regulator.c [new file with mode: 0644]
drivers/regulator/mc13783.c [deleted file]
drivers/regulator/twl-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-ldo.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/scsi/3w-9xxx.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/be2iscsi/be_cmds.c
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/cxgb3i/cxgb3i_offload.c
drivers/scsi/cxgb3i/cxgb3i_pdu.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/hpsa.c [new file with mode: 0644]
drivers/scsi/hpsa.h [new file with mode: 0644]
drivers/scsi/hpsa_cmd.h [new file with mode: 0644]
drivers/scsi/ipr.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/pm8001/pm8001_ctl.h
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pmcraid.c
drivers/scsi/pmcraid.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/st.c
drivers/scsi/st.h
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/atmel_spi.c
drivers/spi/dw_spi.c [new file with mode: 0644]
drivers/spi/dw_spi_pci.c [new file with mode: 0644]
drivers/spi/spi_bfin5xx.c
drivers/spi/spi_mpc8xxx.c
drivers/spi/spi_s3c24xx.c
drivers/spi/spi_s3c24xx_fiq.S [new file with mode: 0644]
drivers/spi/spi_s3c24xx_fiq.h [new file with mode: 0644]
drivers/spi/spi_s3c64xx.c [new file with mode: 0644]
drivers/spi/spi_sh_sci.c
drivers/spi/spi_txx9.c
drivers/spi/spidev.c
drivers/staging/iio/ring_sw.h
drivers/staging/octeon/Kconfig
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/octeon/ethernet-mdio.h
drivers/staging/octeon/ethernet-proc.c
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-sgmii.c
drivers/staging/octeon/ethernet-xaui.c
drivers/staging/octeon/ethernet.c
drivers/staging/octeon/octeon-ethernet.h
drivers/staging/panel/panel.c
drivers/usb/host/ehci-omap.c
drivers/video/atafb.c
drivers/video/backlight/adp5520_bl.c
drivers/video/backlight/adx_bl.c
drivers/video/backlight/atmel-pwm-bl.c
drivers/video/backlight/backlight.c
drivers/video/backlight/corgi_lcd.c
drivers/video/backlight/cr_bllcd.c
drivers/video/backlight/da903x_bl.c
drivers/video/backlight/generic_bl.c
drivers/video/backlight/hp680_bl.c
drivers/video/backlight/jornada720_bl.c
drivers/video/backlight/kb3886_bl.c
drivers/video/backlight/locomolcd.c
drivers/video/backlight/mbp_nvidia_bl.c
drivers/video/backlight/omap1_bl.c
drivers/video/backlight/progear_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/backlight/tosa_bl.c
drivers/video/backlight/wm831x_bl.c
drivers/video/omap/lcd_ldp.c
drivers/video/omap/lcd_omap2evm.c
drivers/video/omap/lcd_omap3beagle.c
drivers/video/omap/lcd_omap3evm.c
drivers/video/omap/lcd_overo.c
drivers/video/via/viafbdev.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/rm9k_wdt.c [deleted file]
fs/Kconfig
fs/anon_inodes.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/binfmt_som.c
fs/btrfs/Kconfig
fs/btrfs/acl.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/dir-item.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/relocation.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/btrfs/xattr.h
fs/direct-io.c
fs/ecryptfs/dentry.c
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/exec.c
fs/ext4/Kconfig
fs/gfs2/Kconfig
fs/gfs2/inode.c
fs/inode.c
fs/jbd/Kconfig
fs/jbd2/Kconfig
fs/jfs/jfs_txnmgr.c
fs/namei.c
fs/namespace.c
fs/nfs/super.c
fs/nilfs2/Kconfig
fs/ntfs/inode.c
fs/pipe.c
fs/ramfs/file-nommu.c
fs/reiserfs/Kconfig
fs/reiserfs/inode.c
fs/stack.c
fs/sync.c
fs/ubifs/file.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/xfs_iget.c
include/asm-generic/fcntl.h
include/linux/Kbuild
include/linux/backlight.h
include/linux/binfmts.h
include/linux/enclosure.h
include/linux/fs.h
include/linux/fs_stack.h
include/linux/init_task.h
include/linux/kmemleak.h
include/linux/leds-lp3944.h
include/linux/leds-pca9532.h
include/linux/leds-regulator.h [new file with mode: 0644]
include/linux/mfd/wm831x/pdata.h
include/linux/mmdebug.h
include/linux/mmzone.h
include/linux/mnt_namespace.h
include/linux/page-flags.h
include/linux/pwm_backlight.h
include/linux/regulator/consumer.h
include/linux/regulator/machine.h
include/linux/regulator/max8660.h [new file with mode: 0644]
include/linux/sched.h
include/linux/security.h
include/linux/spi/dw_spi.h [new file with mode: 0644]
include/linux/vermagic.h
include/linux/vt.h
include/linux/writeback.h
include/scsi/osd_initiator.h
init/Makefile
init/version.c
kernel/bounds.c
kernel/exit.c
kernel/fork.c
kernel/kexec.c
kernel/module.c
kernel/perf_event.c
kernel/printk.c
kernel/sysctl.c
kernel/time/timer_list.c
kernel/trace/trace.c
lib/Kconfig.debug
lib/vsprintf.c
mm/Kconfig
mm/kmemleak.c
mm/readahead.c
mm/slab.c
net/socket.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modbuiltin [new file with mode: 0644]
scripts/basic/fixdep.c
scripts/genksyms/keywords.c_shipped
scripts/genksyms/keywords.gperf
scripts/headers.sh
scripts/kconfig/Makefile
scripts/kconfig/confdata.c
scripts/mkcompile_h
scripts/mod/modpost.c
scripts/package/Makefile
scripts/package/buildtar
scripts/recordmcount.pl
scripts/tags.sh
scripts/unifdef.c
security/Makefile
security/keys/keyctl.c
security/min_addr.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/wm8974.c
sound/soc/omap/sdp3430.c
usr/gen_init_cpio.c

index 946c7ec..fb2190c 100644 (file)
@@ -22,6 +22,7 @@
 *.lst
 *.symtypes
 *.order
+modules.builtin
 *.elf
 *.bin
 *.gz
@@ -45,14 +46,8 @@ Module.symvers
 #
 # Generated include files
 #
-include/asm
-include/asm-*/asm-offsets.h
 include/config
-include/linux/autoconf.h
-include/linux/compile.h
 include/linux/version.h
-include/linux/utsrelease.h
-include/linux/bounds.h
 include/generated
 
 # stgit generated dirs
index 4d4a644..a99d703 100644 (file)
@@ -315,41 +315,26 @@ A: The following are what is required for CPU hotplug infrastructure to work
 
 Q: I need to ensure that a particular cpu is not removed when there is some
    work specific to this cpu is in progress.
-A: First switch the current thread context to preferred cpu
+A: There are two ways.  If your code can be run in interrupt context, use
+   smp_call_function_single(), otherwise use work_on_cpu().  Note that
+   work_on_cpu() is slow, and can fail due to out of memory:
 
        int my_func_on_cpu(int cpu)
        {
-               cpumask_t saved_mask, new_mask = CPU_MASK_NONE;
-               int curr_cpu, err = 0;
-
-               saved_mask = current->cpus_allowed;
-               cpu_set(cpu, new_mask);
-               err = set_cpus_allowed(current, new_mask);
-
-               if (err)
-                       return err;
-
-               /*
-                * If we got scheduled out just after the return from
-                * set_cpus_allowed() before running the work, this ensures
-                * we stay locked.
-                */
-               curr_cpu = get_cpu();
-
-               if (curr_cpu != cpu) {
-                       err = -EAGAIN;
-                       goto ret;
-               } else {
-                       /*
-                        * Do work : But cant sleep, since get_cpu() disables preempt
-                        */
-               }
-               ret:
-                       put_cpu();
-                       set_cpus_allowed(current, saved_mask);
-                       return err;
-               }
-
+               int err;
+               get_online_cpus();
+               if (!cpu_online(cpu))
+                       err = -EINVAL;
+               else
+#if NEEDS_BLOCKING
+                       err = work_on_cpu(cpu, __my_func_on_cpu, NULL);
+#else
+                       smp_call_function_single(cpu, __my_func_on_cpu, &err,
+                                                true);
+#endif
+               put_online_cpus();
+               return err;
+       }
 
 Q: How do we determine how many CPUs are available for hotplug.
 A: There is no clear spec defined way from ACPI that can give us that
index e151b2a..3ad6ace 100644 (file)
@@ -103,6 +103,7 @@ gconf
 gen-devlist
 gen_crc32table
 gen_init_cpio
+generated
 genheaders
 genksyms
 *_gray256.c
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp
new file mode 100644 (file)
index 0000000..a7a18d4
--- /dev/null
@@ -0,0 +1,60 @@
+Kernel driver k10temp
+=====================
+
+Supported chips:
+* AMD Family 10h processors:
+  Socket F: Quad-Core/Six-Core/Embedded Opteron
+  Socket AM2+: Opteron, Phenom (II) X3/X4
+  Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
+  Socket S1G3: Athlon II, Sempron, Turion II
+* AMD Family 11h processors:
+  Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
+
+  Prefix: 'k10temp'
+  Addresses scanned: PCI space
+  Datasheets:
+  BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors:
+    http://support.amd.com/us/Processor_TechDocs/31116.pdf
+  BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41256.pdf
+  Revision Guide for AMD Family 10h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41322.pdf
+  Revision Guide for AMD Family 11h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41788.pdf
+  AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
+    http://support.amd.com/us/Processor_TechDocs/43373.pdf
+  AMD Family 10h Server and Workstation Processor Power and Thermal Data Sheet:
+    http://support.amd.com/us/Processor_TechDocs/43374.pdf
+  AMD Family 10h Desktop Processor Power and Thermal Data Sheet:
+    http://support.amd.com/us/Processor_TechDocs/43375.pdf
+
+Author: Clemens Ladisch <clemens@ladisch.de>
+
+Description
+-----------
+
+This driver permits reading of the internal temperature sensor of AMD
+Family 10h and 11h processors.
+
+All these processors have a sensor, but on older revisions of Family 10h
+processors, the sensor may return inconsistent values (erratum 319). The
+driver will refuse to load on these revisions unless you specify the
+"force=1" module parameter.
+
+There is one temperature measurement value, available as temp1_input in
+sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
+Please note that it is defined as a relative value; to quote the AMD manual:
+
+  Tctl is the processor temperature control value, used by the platform to
+  control cooling systems. Tctl is a non-physical temperature on an
+  arbitrary scale measured in degrees. It does _not_ represent an actual
+  physical temperature like die or case temperature. Instead, it specifies
+  the processor temperature relative to the point at which the system must
+  supply the maximum cooling for the processor's specified maximum case
+  temperature and maximum thermal power dissipation.
+
+The maximum value for Tctl is available in the file temp1_max.
+
+If the BIOS has enabled hardware temperature control, the threshold at
+which the processor will throttle itself to avoid damage is available in
+temp1_crit and temp1_crit_hyst.
index bb3bf38..6f8c1ca 100644 (file)
@@ -1,3 +1,17 @@
+Output files
+
+modules.order
+--------------------------------------------------
+This file records the order in which modules appear in Makefiles. This
+is used by modprobe to deterministically resolve aliases that match
+multiple modules.
+
+modules.builtin
+--------------------------------------------------
+This file lists all modules that are built into the kernel. This is used
+by modprobe to not fail when trying to load something builtin.
+
+
 Environment variables
 
 KCPPFLAGS
index 849b5e5..49efae7 100644 (file)
@@ -103,10 +103,16 @@ KCONFIG_AUTOCONFIG
 This environment variable can be set to specify the path & name of the
 "auto.conf" file.  Its default value is "include/config/auto.conf".
 
+KCONFIG_TRISTATE
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"tristate.conf" file.  Its default value is "include/config/tristate.conf".
+
 KCONFIG_AUTOHEADER
 --------------------------------------------------
 This environment variable can be set to specify the path & name of the
-"autoconf.h" (header) file.  Its default value is "include/linux/autoconf.h".
+"autoconf.h" (header) file.
+Its default value is "include/generated/autoconf.h".
 
 
 ======================================================================
diff --git a/Kbuild b/Kbuild
index f056b4f..e3737ad 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -8,7 +8,7 @@
 #####
 # 1) Generate bounds.h
 
-bounds-file := include/linux/bounds.h
+bounds-file := include/generated/bounds.h
 
 always  := $(bounds-file)
 targets := $(bounds-file) kernel/bounds.s
@@ -43,7 +43,7 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild
 # 2) Generate asm-offsets.h
 #
 
-offsets-file := include/asm/asm-offsets.h
+offsets-file := include/generated/asm-offsets.h
 
 always  += $(offsets-file)
 targets += $(offsets-file)
index 0699782..efd2ef2 100644 (file)
@@ -5434,6 +5434,12 @@ F:       drivers/uwb/*
 F:     include/linux/uwb.h
 F:     include/linux/uwb/
 
+UNIFDEF
+M:     Tony Finch <dot@dotat.at>
+W:     http://dotat.at/prog/unifdef
+S:     Maintained
+F:     scripts/unifdef.c
+
 UNIFORM CDROM DRIVER
 M:     Jens Axboe <axboe@kernel.dk>
 W:     http://www.kernel.dk
index 33d4732..0ac5812 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 32
-EXTRAVERSION =
+SUBLEVEL = 33
+EXTRAVERSION = -rc1
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -334,10 +334,9 @@ CFLAGS_GCOV        = -fprofile-arcs -ftest-coverage
 
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
-LINUXINCLUDE    := -Iinclude \
-                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-                   -I$(srctree)/arch/$(hdr-arch)/include               \
-                   -include include/linux/autoconf.h
+LINUXINCLUDE    := -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \
+                   $(if $(KBUILD_SRC), -I$(srctree)/include) \
+                   -include include/generated/autoconf.h
 
 KBUILD_CPPFLAGS := -D__KERNEL__
 
@@ -465,7 +464,7 @@ ifeq ($(KBUILD_EXTMOD),)
 # Carefully list dependencies so we do not try to build scripts twice
 # in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/auto.conf
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
        $(Q)$(MAKE) $(build)=$(@)
 
 # Objects we will link into vmlinux / subdirs we need to visit
@@ -492,18 +491,18 @@ $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
 # with it and forgot to run make oldconfig.
 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
-include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
        $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
-# external modules needs include/linux/autoconf.h and include/config/auto.conf
+# external modules needs include/generated/autoconf.h and include/config/auto.conf
 # but do not care if they are up-to-date. Use auto.conf to trigger the test
 PHONY += include/config/auto.conf
 
 include/config/auto.conf:
-       $(Q)test -e include/linux/autoconf.h -a -e $@ || (              \
+       $(Q)test -e include/generated/autoconf.h -a -e $@ || (          \
        echo;                                                           \
        echo "  ERROR: Kernel configuration is invalid.";               \
-       echo "         include/linux/autoconf.h or $@ are missing.";    \
+       echo "         include/generated/autoconf.h or $@ are missing.";\
        echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
        echo;                                                           \
        /bin/false)
@@ -877,6 +876,9 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
 PHONY += $(vmlinux-dirs)
 $(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
+ifdef CONFIG_MODULES
+       $(Q)$(MAKE) $(modbuiltin)=$@
+endif
 
 # Build the kernel release string
 #
@@ -955,7 +957,6 @@ PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
-# 2) Create the include2 directory, used for the second asm symlink
 prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
        @$(kecho) '  Using $(srctree) as source for kernel'
@@ -964,17 +965,13 @@ ifneq ($(KBUILD_SRC),)
                echo "  in the '$(srctree)' directory.";\
                /bin/false; \
        fi;
-       $(Q)if [ ! -d include2 ]; then                                  \
-           mkdir -p include2;                                          \
-           ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
-       fi
 endif
 
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile
 
-prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
-                   include/asm include/config/auto.conf
+prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
+                   include/config/auto.conf
        $(cmd_crmodverdir)
 
 archprepare: prepare1 scripts_basic
@@ -986,42 +983,6 @@ prepare0: archprepare FORCE
 # All the preparing..
 prepare: prepare0
 
-# The asm symlink changes when $(ARCH) changes.
-# Detect this and ask user to run make mrproper
-# If asm is a stale symlink (point to dir that does not exist) remove it
-define check-symlink
-       set -e;                                                            \
-       if [ -L include/asm ]; then                                        \
-               asmlink=`readlink include/asm | cut -d '-' -f 2`;          \
-               if [ "$$asmlink" != "$(SRCARCH)" ]; then                   \
-                       echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
-                       echo "       set ARCH or save .config and run 'make mrproper' to fix it";             \
-                       exit 1;                                            \
-               fi;                                                        \
-               test -e $$asmlink || rm include/asm;                       \
-       elif [ -d include/asm ]; then                                      \
-               echo "ERROR: $@ is a directory but a symlink was expected";\
-               exit 1;                                                    \
-       fi
-endef
-
-# We create the target directory of the symlink if it does
-# not exist so the test in check-symlink works and we have a
-# directory for generated filesas used by some architectures.
-define create-symlink
-       if [ ! -L include/asm ]; then                                      \
-                       $(kecho) '  SYMLINK $@ -> include/asm-$(SRCARCH)'; \
-                       if [ ! -d include/asm-$(SRCARCH) ]; then           \
-                               mkdir -p include/asm-$(SRCARCH);           \
-                       fi;                                                \
-                       ln -fsn asm-$(SRCARCH) $@;                         \
-       fi
-endef
-
-include/asm: FORCE
-       $(Q)$(check-symlink)
-       $(Q)$(create-symlink)
-
 # Generate some files
 # ---------------------------------------------------------------------------
 
@@ -1046,7 +1007,7 @@ endef
 include/linux/version.h: $(srctree)/Makefile FORCE
        $(call filechk,version.h)
 
-include/linux/utsrelease.h: include/config/kernel.release FORCE
+include/generated/utsrelease.h: include/config/kernel.release FORCE
        $(call filechk,utsrelease.h)
 
 PHONY += headerdep
@@ -1076,11 +1037,6 @@ firmware_install: FORCE
 export INSTALL_HDR_PATH = $(objtree)/usr
 
 hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
-# Find out where the Kbuild file is located to support
-# arch/$(ARCH)/include/asm
-hdr-dir = $(strip                                                         \
-          $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
-               arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
 
 # If we do an all arch process set dst to asm-$(hdr-arch)
 hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
@@ -1095,10 +1051,10 @@ headers_install_all:
 
 PHONY += headers_install
 headers_install: __headers
-       $(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
+       $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \
        $(error Headers not exportable for the $(SRCARCH) architecture))
        $(Q)$(MAKE) $(hdr-inst)=include
-       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -1107,7 +1063,7 @@ headers_check_all: headers_install_all
 PHONY += headers_check
 headers_check: headers_install
        $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
-       $(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
@@ -1127,6 +1083,7 @@ all: modules
 PHONY += modules
 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
        $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
+       $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.builtin) > $(objtree)/modules.builtin
        @$(kecho) '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
@@ -1156,6 +1113,7 @@ _modinst_:
                ln -s $(objtree) $(MODLIB)/build ; \
        fi
        @cp -f $(objtree)/modules.order $(MODLIB)/
+       @cp -f $(objtree)/modules.builtin $(MODLIB)/
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
 
 # This depmod is only for convenience to give the initial
@@ -1194,12 +1152,10 @@ CLEAN_FILES +=  vmlinux System.map \
                 .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
 
 # Directories & files removed with 'make mrproper'
-MRPROPER_DIRS  += include/config include2 usr/include include/generated
-MRPROPER_FILES += .config .config.old include/asm .version .old_version \
-                  include/linux/autoconf.h include/linux/version.h      \
-                  include/linux/utsrelease.h                            \
-                  include/linux/bounds.h include/asm*/asm-offsets.h     \
-                 Module.symvers Module.markers tags TAGS cscope*
+MRPROPER_DIRS  += include/config usr/include include/generated
+MRPROPER_FILES += .config .config.old .version .old_version             \
+                  include/linux/version.h                               \
+                 Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1218,7 +1174,7 @@ clean: archclean $(clean-dirs)
                \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.symtypes' -o -name 'modules.order' \
-               -o -name 'Module.markers' -o -name '.tmp_*.o.*' \
+               -o -name modules.builtin -o -name '.tmp_*.o.*' \
                -o -name '*.gcno' \) -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -1416,8 +1372,8 @@ $(clean-dirs):
 
 clean: rm-dirs := $(MODVERDIR)
 clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
-                   $(KBUILD_EXTMOD)/Module.markers \
-                   $(KBUILD_EXTMOD)/modules.order
+                   $(KBUILD_EXTMOD)/modules.order \
+                   $(KBUILD_EXTMOD)/modules.builtin
 clean: $(clean-dirs)
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
index 3af21c7..3c8d1b2 100644 (file)
@@ -9,7 +9,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
index 1036b51..ade3f12 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
index 89f3be0..644b7db 100644 (file)
@@ -7,7 +7,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
diff --git a/arch/alpha/include/asm/asm-offsets.h b/arch/alpha/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 21b1117..70145cb 100644 (file)
@@ -16,7 +16,7 @@
 #define O_NOATIME      04000000
 #define O_CLOEXEC      010000000 /* set close_on_exec */
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
index fa0cdab..e9da084 100644 (file)
@@ -242,15 +242,8 @@ all:       $(KBUILD_IMAGE)
 
 boot := arch/arm/boot
 
-#      Update machine arch and proc symlinks if something which affects
-#      them changed.  We use .arch to indicate when they were updated
-#      last, otherwise make uses the target directory mtime.
-
-archprepare: maketools
-
-PHONY += maketools FORCE
-maketools: include/linux/version.h FORCE
-       $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
+archprepare:
+       $(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h
 
 # Convert bzImage to zImage
 bzImage: zImage
@@ -261,9 +254,6 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-CLEAN_FILES += include/asm-arm/mach-types.h \
-              include/asm-arm/arch include/asm-arm/.arch
-
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
index 5a375e5..bc90364 100644 (file)
@@ -308,15 +308,11 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
                        memcpy(ptr, buf->safe, size);
 
                        /*
-                        * DMA buffers must have the same cache properties
-                        * as if they were really used for DMA - which means
-                        * data must be written back to RAM.  Note that
-                        * we don't use dmac_flush_range() here for the
-                        * bidirectional case because we know the cache
-                        * lines will be coherent with the data written.
+                        * Since we may have written to a page cache page,
+                        * we need to ensure that the data will be coherent
+                        * with user mappings.
                         */
-                       dmac_clean_range(ptr, ptr + size);
-                       outer_clean_range(__pa(ptr), __pa(ptr) + size);
+                       __cpuc_flush_kernel_dcache_area(ptr, size);
                }
                free_safe_buffer(dev->archdata.dmabounce, buf);
        }
diff --git a/arch/arm/include/asm/asm-offsets.h b/arch/arm/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 73eceb8..730aefc 100644 (file)
@@ -211,7 +211,7 @@ struct cpu_cache_fns {
 
        void (*coherent_kern_range)(unsigned long, unsigned long);
        void (*coherent_user_range)(unsigned long, unsigned long);
-       void (*flush_kern_dcache_page)(void *);
+       void (*flush_kern_dcache_area)(void *, size_t);
 
        void (*dma_inv_range)(const void *, const void *);
        void (*dma_clean_range)(const void *, const void *);
@@ -236,7 +236,7 @@ extern struct cpu_cache_fns cpu_cache;
 #define __cpuc_flush_user_range                cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range     cpu_cache.coherent_kern_range
 #define __cpuc_coherent_user_range     cpu_cache.coherent_user_range
-#define __cpuc_flush_dcache_page       cpu_cache.flush_kern_dcache_page
+#define __cpuc_flush_dcache_area       cpu_cache.flush_kern_dcache_area
 
 /*
  * These are private to the dma-mapping API.  Do not use directly.
@@ -255,14 +255,14 @@ extern struct cpu_cache_fns cpu_cache;
 #define __cpuc_flush_user_range                __glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range     __glue(_CACHE,_coherent_kern_range)
 #define __cpuc_coherent_user_range     __glue(_CACHE,_coherent_user_range)
-#define __cpuc_flush_dcache_page       __glue(_CACHE,_flush_kern_dcache_page)
+#define __cpuc_flush_dcache_area       __glue(_CACHE,_flush_kern_dcache_area)
 
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
 extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
-extern void __cpuc_flush_dcache_page(void *);
+extern void __cpuc_flush_dcache_area(void *, size_t);
 
 /*
  * These are private to the dma-mapping API.  Do not use directly.
@@ -448,7 +448,7 @@ static inline void flush_kernel_dcache_page(struct page *page)
 {
        /* highmem pages are always flushed upon kunmap already */
        if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
-               __cpuc_flush_dcache_page(page_address(page));
+               __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 
 #define flush_dcache_mmap_lock(mapping) \
@@ -465,13 +465,6 @@ static inline void flush_kernel_dcache_page(struct page *page)
  */
 #define flush_icache_page(vma,page)    do { } while (0)
 
-static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt,
-       unsigned offset, size_t size)
-{
-       const void *start = (void __force *)virt + offset;
-       dmac_inv_range(start, start + size);
-}
-
 /*
  * flush_cache_vmap() is used when creating mappings (eg, via vmap,
  * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
new file mode 100644 (file)
index 0000000..948178c
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/mach-types.h>
index 8bf09ae..f6c6196 100644 (file)
@@ -52,6 +52,12 @@ config MACH_OPENRD_BASE
          Say 'Y' here if you want your kernel to support the
          Marvell OpenRD Base Board.
 
+config MACH_NETSPACE_V2
+       bool "LaCie Network Space v2 NAS Board"
+       help
+         Say 'Y' here if you want your kernel to support the
+         LaCie Network Space v2 NAS.
+
 endmenu
 
 endif
index 9f2f67b..d4d7f53 100644 (file)
@@ -8,5 +8,6 @@ obj-$(CONFIG_MACH_SHEEVAPLUG)           += sheevaplug-setup.o
 obj-$(CONFIG_MACH_TS219)               += ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)               += ts41x-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_OPENRD_BASE)         += openrd_base-setup.o
+obj-$(CONFIG_MACH_NETSPACE_V2)         += netspace_v2-setup.o
 
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
new file mode 100644 (file)
index 0000000..9a06406
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * arch/arm/mach-kirkwood/netspace_v2-setup.c
+ *
+ * LaCie Network Space v2 board setup
+ *
+ * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com>
+ * Copyright (C) 2009 Benoît Canet <benoit.canet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/kirkwood.h>
+#include <plat/time.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
+ ****************************************************************************/
+
+static struct mtd_partition netspace_v2_flash_parts[] = {
+       {
+               .name = "u-boot",
+               .size = MTDPART_SIZ_FULL,
+               .offset = 0,
+               .mask_flags = MTD_WRITEABLE, /* force read-only */
+       },
+};
+
+static const struct flash_platform_data netspace_v2_flash = {
+       .type           = "mx25l4005a",
+       .name           = "spi_flash",
+       .parts          = netspace_v2_flash_parts,
+       .nr_parts       = ARRAY_SIZE(netspace_v2_flash_parts),
+};
+
+static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = {
+       {
+               .modalias       = "m25p80",
+               .platform_data  = &netspace_v2_flash,
+               .irq            = -1,
+               .max_speed_hz   = 20000000,
+               .bus_num        = 0,
+               .chip_select    = 0,
+       },
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data netspace_v2_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * I2C devices
+ ****************************************************************************/
+
+static struct at24_platform_data at24c04 = {
+       .byte_len       = SZ_4K / 8,
+       .page_size      = 16,
+};
+
+/*
+ * i2c addr | chip         | description
+ * 0x50     | HT24LC04     | eeprom (512B)
+ */
+
+static struct i2c_board_info __initdata netspace_v2_i2c_info[] = {
+       {
+               I2C_BOARD_INFO("24c04", 0x50),
+               .platform_data  = &at24c04,
+       }
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+
+static struct mv_sata_platform_data netspace_v2_sata_data = {
+       .n_ports        = 2,
+};
+
+#define NETSPACE_V2_GPIO_SATA0_POWER   16
+#define NETSPACE_V2_GPIO_SATA1_POWER   17
+
+static void __init netspace_v2_sata_power_init(void)
+{
+       int err;
+
+       err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power");
+       if (err == 0) {
+               err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1);
+               if (err)
+                       gpio_free(NETSPACE_V2_GPIO_SATA0_POWER);
+       }
+       if (err)
+               pr_err("netspace_v2: failed to setup SATA0 power\n");
+}
+
+/*****************************************************************************
+ * GPIO keys
+ ****************************************************************************/
+
+#define NETSPACE_V2_PUSH_BUTTON                32
+
+static struct gpio_keys_button netspace_v2_buttons[] = {
+       [0] = {
+               .code           = KEY_POWER,
+               .gpio           = NETSPACE_V2_PUSH_BUTTON,
+               .desc           = "Power push button",
+               .active_low     = 0,
+       },
+};
+
+static struct gpio_keys_platform_data netspace_v2_button_data = {
+       .buttons        = netspace_v2_buttons,
+       .nbuttons       = ARRAY_SIZE(netspace_v2_buttons),
+};
+
+static struct platform_device netspace_v2_gpio_buttons = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &netspace_v2_button_data,
+       },
+};
+
+/*****************************************************************************
+ * GPIO LEDs
+ ****************************************************************************/
+
+/*
+ * The blue front LED is wired to a CPLD and can blink in relation with the
+ * SATA activity.
+ *
+ * The following array detail the different LED registers and the combination
+ * of their possible values:
+ *
+ *  cmd_led   |  slow_led  | /SATA active | LED state
+ *            |            |              |
+ *     1      |     0      |      x       |  off
+ *     -      |     1      |      x       |  on
+ *     0      |     0      |      1       |  on
+ *     0      |     0      |      0       |  blink (rate 300ms)
+ */
+
+#define NETSPACE_V2_GPIO_RED_LED       12
+#define NETSPACE_V2_GPIO_BLUE_LED_SLOW 29
+#define NETSPACE_V2_GPIO_BLUE_LED_CMD  30
+
+
+static struct gpio_led netspace_v2_gpio_led_pins[] = {
+       {
+               .name   = "ns_v2:red:fail",
+               .gpio   = NETSPACE_V2_GPIO_RED_LED,
+       },
+};
+
+static struct gpio_led_platform_data netspace_v2_gpio_leds_data = {
+       .num_leds       = ARRAY_SIZE(netspace_v2_gpio_led_pins),
+       .leds           = netspace_v2_gpio_led_pins,
+};
+
+static struct platform_device netspace_v2_gpio_leds = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &netspace_v2_gpio_leds_data,
+       },
+};
+
+static void __init netspace_v2_gpio_leds_init(void)
+{
+       platform_device_register(&netspace_v2_gpio_leds);
+
+       /*
+        * Configure the front blue LED to blink in relation with the SATA
+        * activity.
+        */
+       if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_SLOW,
+                        "SATA blue LED slow") != 0)
+               return;
+       if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_SLOW, 0) != 0)
+               goto err_free_1;
+       if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_CMD,
+                        "SATA blue LED command") != 0)
+               goto err_free_1;
+       if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_CMD, 0) != 0)
+               goto err_free_2;
+
+       return;
+
+err_free_2:
+       gpio_free(NETSPACE_V2_GPIO_BLUE_LED_CMD);
+err_free_1:
+       gpio_free(NETSPACE_V2_GPIO_BLUE_LED_SLOW);
+       pr_err("netspace_v2: failed to configure SATA blue LED\n");
+}
+
+/*****************************************************************************
+ * Timer
+ ****************************************************************************/
+
+static void netspace_v2_timer_init(void)
+{
+       kirkwood_tclk = 166666667;
+       orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+}
+
+struct sys_timer netspace_v2_timer = {
+       .init = netspace_v2_timer_init,
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+static unsigned int netspace_v2_mpp_config[] __initdata = {
+       MPP0_SPI_SCn,
+       MPP1_SPI_MOSI,
+       MPP2_SPI_SCK,
+       MPP3_SPI_MISO,
+       MPP4_NF_IO6,
+       MPP5_NF_IO7,
+       MPP6_SYSRST_OUTn,
+       MPP8_TW_SDA,
+       MPP9_TW_SCK,
+       MPP10_UART0_TXD,
+       MPP11_UART0_RXD,
+       MPP12_GPO,              /* Red led */
+       MPP14_GPIO,             /* USB fuse */
+       MPP16_GPIO,             /* SATA 0 power */
+       MPP18_NF_IO0,
+       MPP19_NF_IO1,
+       MPP20_SATA1_ACTn,
+       MPP21_SATA0_ACTn,
+       MPP24_GPIO,             /* USB mode select */
+       MPP25_GPIO,             /* Fan rotation fail */
+       MPP26_GPIO,             /* USB device vbus */
+       MPP28_GPIO,             /* USB enable host vbus */
+       MPP29_GPIO,             /* Blue led (slow register) */
+       MPP30_GPIO,             /* Blue led (command register) */
+       MPP31_GPIO,             /* Board power off */
+       MPP32_GPIO,             /* Power button (0 = Released, 1 = Pushed) */
+       0
+};
+
+#define NETSPACE_V2_GPIO_POWER_OFF     31
+
+static void netspace_v2_power_off(void)
+{
+       gpio_set_value(NETSPACE_V2_GPIO_POWER_OFF, 1);
+}
+
+static void __init netspace_v2_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_init();
+       kirkwood_mpp_conf(netspace_v2_mpp_config);
+
+       netspace_v2_sata_power_init();
+
+       kirkwood_ehci_init();
+       kirkwood_ge00_init(&netspace_v2_ge00_data);
+       kirkwood_sata_init(&netspace_v2_sata_data);
+       kirkwood_uart0_init();
+       spi_register_board_info(netspace_v2_spi_slave_info,
+                               ARRAY_SIZE(netspace_v2_spi_slave_info));
+       kirkwood_spi_init();
+       kirkwood_i2c_init();
+       i2c_register_board_info(0, netspace_v2_i2c_info,
+                               ARRAY_SIZE(netspace_v2_i2c_info));
+
+       netspace_v2_gpio_leds_init();
+       platform_device_register(&netspace_v2_gpio_buttons);
+
+       if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
+           gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
+               pm_power_off = netspace_v2_power_off;
+       else
+               pr_err("netspace_v2: failed to configure power-off GPIO\n");
+}
+
+MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
+       .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
+       .io_pg_offst    = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .init_machine   = netspace_v2_init,
+       .map_io         = kirkwood_map_io,
+       .init_irq       = kirkwood_init_irq,
+       .timer          = &netspace_v2_timer,
+MACHINE_END
index 76c11ee..10eafa7 100644 (file)
@@ -18,6 +18,7 @@ config ARCH_OMAP2430
 config ARCH_OMAP34XX
        bool "OMAP34xx Based System"
        depends on ARCH_OMAP3
+       select USB_ARCH_HAS_EHCI
 
 config ARCH_OMAP3430
        bool "OMAP3430 support"
index 1591aae..2626a9f 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/gpio.h>
 
 #include <linux/i2c/at24.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
index 44239e3..117b8fd 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index 18913e9..34de178 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 #include <linux/usb/otg.h>
 #include <linux/smsc911x.h>
 
index c9e5ebb..fe3d22c 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/spi/ads7846.h>
 
 #include <linux/regulator/machine.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
index 17f3c91..acafdbc 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/wl12xx.h>
 #include <linux/i2c.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/regulator/machine.h>
index 258794d..8dd277c 100755 (executable)
@@ -14,7 +14,7 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
index 39b797b..19805a7 100644 (file)
@@ -640,12 +640,9 @@ void __init omap_serial_early_init(void)
                uart->num = i;
                p->private_data = uart;
                uart->p = p;
-               list_add_tail(&uart->node, &uart_list);
 
                if (cpu_is_omap44xx())
                        p->irq += 32;
-
-               omap_uart_enable_clocks(uart);
        }
 }
 
@@ -673,9 +670,13 @@ void __init omap_serial_init_port(int port)
        pdev = &uart->pdev;
        dev = &pdev->dev;
 
+       omap_uart_enable_clocks(uart);
+
        omap_uart_reset(uart);
        omap_uart_idle_init(uart);
 
+       list_add_tail(&uart->node, &uart_list);
+
        if (WARN_ON(platform_device_register(pdev)))
                return;
 
index e6d8e10..8a0837e 100644 (file)
@@ -110,6 +110,8 @@ config MACH_CM_X300
        bool "CompuLab CM-X300 modules"
        select PXA3xx
        select CPU_PXA300
+       select CPU_PXA310
+       select HAVE_PWM
 
 config ARCH_GUMSTIX
        bool "Gumstix XScale 255 boards"
@@ -240,7 +242,6 @@ config MACH_COLIBRI300
        select PXA3xx
        select CPU_PXA300
        select CPU_PXA310
-       select HAVE_PWM
 
 config MACH_COLIBRI320
        bool "Toradex Colibri PXA320"
index 3395463..8e10db1 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 
-#include <mach/hardware.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
@@ -14,6 +13,7 @@
 #include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
+#include <mach/hardware.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
index 193b39d..4d95883 100644 (file)
@@ -18,6 +18,8 @@ struct s3c2410_spi_info {
        unsigned int             num_cs;        /* total chipselects */
        int                      bus_num;       /* bus number to use. */
 
+       unsigned int             use_fiq:1;     /* use fiq */
+
        void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
        void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
index b63a8f7..a89444a 100644 (file)
@@ -127,15 +127,16 @@ ENTRY(fa_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(kaddr)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     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)
+ *     - addr  - kernel address
+ *     - size  - size of region
  */
-ENTRY(fa_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(fa_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -213,7 +214,7 @@ ENTRY(fa_cache_fns)
        .long   fa_flush_user_cache_range
        .long   fa_coherent_kern_range
        .long   fa_coherent_user_range
-       .long   fa_flush_kern_dcache_page
+       .long   fa_flush_kern_dcache_area
        .long   fa_dma_inv_range
        .long   fa_dma_clean_range
        .long   fa_dma_flush_range
index 747f9a9..cb8fc65 100644 (file)
 static void __iomem *l2x0_base;
 static DEFINE_SPINLOCK(l2x0_lock);
 
-static inline void sync_writel(unsigned long val, unsigned long reg,
-                              unsigned long complete_mask)
+static inline void cache_wait(void __iomem *reg, unsigned long mask)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&l2x0_lock, flags);
-       writel(val, l2x0_base + reg);
        /* wait for the operation to complete */
-       while (readl(l2x0_base + reg) & complete_mask)
+       while (readl(reg) & mask)
                ;
-       spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static inline void cache_sync(void)
 {
-       sync_writel(0, L2X0_CACHE_SYNC, 1);
+       void __iomem *base = l2x0_base;
+       writel(0, base + L2X0_CACHE_SYNC);
+       cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
 static inline void l2x0_inv_all(void)
 {
+       unsigned long flags;
+
        /* invalidate all ways */
-       sync_writel(0xff, L2X0_INV_WAY, 0xff);
+       spin_lock_irqsave(&l2x0_lock, flags);
+       writel(0xff, l2x0_base + L2X0_INV_WAY);
+       cache_wait(l2x0_base + L2X0_INV_WAY, 0xff);
        cache_sync();
+       spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_range(unsigned long start, unsigned long end)
 {
-       unsigned long addr;
+       void __iomem *base = l2x0_base;
+       unsigned long flags;
 
+       spin_lock_irqsave(&l2x0_lock, flags);
        if (start & (CACHE_LINE_SIZE - 1)) {
                start &= ~(CACHE_LINE_SIZE - 1);
-               sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1);
+               cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+               writel(start, base + L2X0_CLEAN_INV_LINE_PA);
                start += CACHE_LINE_SIZE;
        }
 
        if (end & (CACHE_LINE_SIZE - 1)) {
                end &= ~(CACHE_LINE_SIZE - 1);
-               sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1);
+               cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+               writel(end, base + L2X0_CLEAN_INV_LINE_PA);
        }
 
-       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-               sync_writel(addr, L2X0_INV_LINE_PA, 1);
+       while (start < end) {
+               unsigned long blk_end = start + min(end - start, 4096UL);
+
+               while (start < blk_end) {
+                       cache_wait(base + L2X0_INV_LINE_PA, 1);
+                       writel(start, base + L2X0_INV_LINE_PA);
+                       start += CACHE_LINE_SIZE;
+               }
+
+               if (blk_end < end) {
+                       spin_unlock_irqrestore(&l2x0_lock, flags);
+                       spin_lock_irqsave(&l2x0_lock, flags);
+               }
+       }
+       cache_wait(base + L2X0_INV_LINE_PA, 1);
        cache_sync();
+       spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_range(unsigned long start, unsigned long end)
 {
-       unsigned long addr;
+       void __iomem *base = l2x0_base;
+       unsigned long flags;
 
+       spin_lock_irqsave(&l2x0_lock, flags);
        start &= ~(CACHE_LINE_SIZE - 1);
-       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-               sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
+       while (start < end) {
+               unsigned long blk_end = start + min(end - start, 4096UL);
+
+               while (start < blk_end) {
+                       cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
+                       writel(start, base + L2X0_CLEAN_LINE_PA);
+                       start += CACHE_LINE_SIZE;
+               }
+
+               if (blk_end < end) {
+                       spin_unlock_irqrestore(&l2x0_lock, flags);
+                       spin_lock_irqsave(&l2x0_lock, flags);
+               }
+       }
+       cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
        cache_sync();
+       spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_flush_range(unsigned long start, unsigned long end)
 {
-       unsigned long addr;
+       void __iomem *base = l2x0_base;
+       unsigned long flags;
 
+       spin_lock_irqsave(&l2x0_lock, flags);
        start &= ~(CACHE_LINE_SIZE - 1);
-       for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-               sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
+       while (start < end) {
+               unsigned long blk_end = start + min(end - start, 4096UL);
+
+               while (start < blk_end) {
+                       cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+                       writel(start, base + L2X0_CLEAN_INV_LINE_PA);
+                       start += CACHE_LINE_SIZE;
+               }
+
+               if (blk_end < end) {
+                       spin_unlock_irqrestore(&l2x0_lock, flags);
+                       spin_lock_irqsave(&l2x0_lock, flags);
+               }
+       }
+       cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
        cache_sync();
+       spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
index 8a4abeb..2a48273 100644 (file)
@@ -72,14 +72,15 @@ ENTRY(v3_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *page, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v3_flush_kern_dcache_page)
+ENTRY(v3_flush_kern_dcache_area)
        /* FALLTHROUGH */
 
 /*
@@ -129,7 +130,7 @@ ENTRY(v3_cache_fns)
        .long   v3_flush_user_cache_range
        .long   v3_coherent_kern_range
        .long   v3_coherent_user_range
-       .long   v3_flush_kern_dcache_page
+       .long   v3_flush_kern_dcache_area
        .long   v3_dma_inv_range
        .long   v3_dma_clean_range
        .long   v3_dma_flush_range
index 3668611..5c7da3e 100644 (file)
@@ -82,14 +82,15 @@ ENTRY(v4_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v4_flush_kern_dcache_page)
+ENTRY(v4_flush_kern_dcache_area)
        /* FALLTHROUGH */
 
 /*
@@ -141,7 +142,7 @@ ENTRY(v4_cache_fns)
        .long   v4_flush_user_cache_range
        .long   v4_coherent_kern_range
        .long   v4_coherent_user_range
-       .long   v4_flush_kern_dcache_page
+       .long   v4_flush_kern_dcache_area
        .long   v4_dma_inv_range
        .long   v4_dma_clean_range
        .long   v4_dma_flush_range
index 2ebc1b3..3dbedf1 100644 (file)
@@ -114,15 +114,16 @@ ENTRY(v4wb_flush_user_cache_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v4wb_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(v4wb_flush_kern_dcache_area)
+       add     r1, r0, r1
        /* fall through */
 
 /*
@@ -224,7 +225,7 @@ ENTRY(v4wb_cache_fns)
        .long   v4wb_flush_user_cache_range
        .long   v4wb_coherent_kern_range
        .long   v4wb_coherent_user_range
-       .long   v4wb_flush_kern_dcache_page
+       .long   v4wb_flush_kern_dcache_area
        .long   v4wb_dma_inv_range
        .long   v4wb_dma_clean_range
        .long   v4wb_dma_flush_range
index c54fa2c..b3b7410 100644 (file)
@@ -117,17 +117,18 @@ ENTRY(v4wt_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v4wt_flush_kern_dcache_page)
+ENTRY(v4wt_flush_kern_dcache_area)
        mov     r2, #0
        mcr     p15, 0, r2, c7, c5, 0           @ invalidate I cache
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
        /* fallthrough */
 
 /*
@@ -180,7 +181,7 @@ ENTRY(v4wt_cache_fns)
        .long   v4wt_flush_user_cache_range
        .long   v4wt_coherent_kern_range
        .long   v4wt_coherent_user_range
-       .long   v4wt_flush_kern_dcache_page
+       .long   v4wt_flush_kern_dcache_area
        .long   v4wt_dma_inv_range
        .long   v4wt_dma_clean_range
        .long   v4wt_dma_flush_range
index 295e25d..4ba0a24 100644 (file)
@@ -159,15 +159,16 @@ ENDPROC(v6_coherent_user_range)
 ENDPROC(v6_coherent_kern_range)
 
 /*
- *     v6_flush_kern_dcache_page(kaddr)
+ *     v6_flush_kern_dcache_area(void *addr, size_t size)
  *
  *     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)
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v6_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(v6_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
@@ -271,7 +272,7 @@ ENTRY(v6_cache_fns)
        .long   v6_flush_user_cache_range
        .long   v6_coherent_kern_range
        .long   v6_coherent_user_range
-       .long   v6_flush_kern_dcache_page
+       .long   v6_flush_kern_dcache_area
        .long   v6_dma_inv_range
        .long   v6_dma_clean_range
        .long   v6_dma_flush_range
index e1bd975..9073db8 100644 (file)
@@ -186,16 +186,17 @@ ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
 
 /*
- *     v7_flush_kern_dcache_page(kaddr)
+ *     v7_flush_kern_dcache_area(void *addr, size_t size)
  *
  *     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)
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(v7_flush_kern_dcache_page)
+ENTRY(v7_flush_kern_dcache_area)
        dcache_line_size r2, r3
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
 1:
        mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line / unified line
        add     r0, r0, r2
@@ -203,7 +204,7 @@ ENTRY(v7_flush_kern_dcache_page)
        blo     1b
        dsb
        mov     pc, lr
-ENDPROC(v7_flush_kern_dcache_page)
+ENDPROC(v7_flush_kern_dcache_area)
 
 /*
  *     v7_dma_inv_range(start,end)
@@ -279,7 +280,7 @@ ENTRY(v7_cache_fns)
        .long   v7_flush_user_cache_range
        .long   v7_coherent_kern_range
        .long   v7_coherent_user_range
-       .long   v7_flush_kern_dcache_page
+       .long   v7_flush_kern_dcache_area
        .long   v7_dma_inv_range
        .long   v7_dma_clean_range
        .long   v7_dma_flush_range
index 329594e..6f3a4b7 100644 (file)
@@ -131,7 +131,7 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
         */
        if (addr)
 #endif
-               __cpuc_flush_dcache_page(addr);
+               __cpuc_flush_dcache_area(addr, PAGE_SIZE);
 
        /*
         * If this is a page cache page, and we have an aliasing VIPT cache,
@@ -258,5 +258,5 @@ void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned l
         * in this mapping of the page.  FIXME: this is overkill
         * since we actually ask for a write-back and invalidate.
         */
-       __cpuc_flush_dcache_page(page_address(page));
+       __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
index 30f82fb..2be1ec7 100644 (file)
@@ -79,7 +79,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
        unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
 
        if (kvaddr >= (void *)FIXADDR_START) {
-               __cpuc_flush_dcache_page((void *)vaddr);
+               __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
                BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
                set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
index 900811c..374a831 100644 (file)
@@ -61,7 +61,7 @@ void setup_mm_for_reboot(char mode)
 
 void flush_dcache_page(struct page *page)
 {
-       __cpuc_flush_dcache_page(page_address(page));
+       __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
index d9fb4b9..8012e24 100644 (file)
@@ -231,17 +231,18 @@ ENTRY(arm1020_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - page  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm1020_flush_kern_dcache_page)
+ENTRY(arm1020_flush_kern_dcache_area)
        mov     ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
        add     r0, r0, #CACHE_DLINESIZE
@@ -335,7 +336,7 @@ ENTRY(arm1020_cache_fns)
        .long   arm1020_flush_user_cache_range
        .long   arm1020_coherent_kern_range
        .long   arm1020_coherent_user_range
-       .long   arm1020_flush_kern_dcache_page
+       .long   arm1020_flush_kern_dcache_area
        .long   arm1020_dma_inv_range
        .long   arm1020_dma_clean_range
        .long   arm1020_dma_flush_range
index 7453b75..41fe25d 100644 (file)
@@ -225,17 +225,18 @@ ENTRY(arm1020e_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - page  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm1020e_flush_kern_dcache_page)
+ENTRY(arm1020e_flush_kern_dcache_area)
        mov     ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -321,7 +322,7 @@ ENTRY(arm1020e_cache_fns)
        .long   arm1020e_flush_user_cache_range
        .long   arm1020e_coherent_kern_range
        .long   arm1020e_coherent_user_range
-       .long   arm1020e_flush_kern_dcache_page
+       .long   arm1020e_flush_kern_dcache_area
        .long   arm1020e_dma_inv_range
        .long   arm1020e_dma_clean_range
        .long   arm1020e_dma_flush_range
index 8eb72d7..20a5b1b 100644 (file)
@@ -214,17 +214,18 @@ ENTRY(arm1022_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - page  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm1022_flush_kern_dcache_page)
+ENTRY(arm1022_flush_kern_dcache_area)
        mov     ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -310,7 +311,7 @@ ENTRY(arm1022_cache_fns)
        .long   arm1022_flush_user_cache_range
        .long   arm1022_coherent_kern_range
        .long   arm1022_coherent_user_range
-       .long   arm1022_flush_kern_dcache_page
+       .long   arm1022_flush_kern_dcache_area
        .long   arm1022_dma_inv_range
        .long   arm1022_dma_clean_range
        .long   arm1022_dma_flush_range
index 3b59f0d..96aedb1 100644 (file)
@@ -208,17 +208,18 @@ ENTRY(arm1026_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - page  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm1026_flush_kern_dcache_page)
+ENTRY(arm1026_flush_kern_dcache_area)
        mov     ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-       add     r1, r0, #PAGE_SZ
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -304,7 +305,7 @@ ENTRY(arm1026_cache_fns)
        .long   arm1026_flush_user_cache_range
        .long   arm1026_coherent_kern_range
        .long   arm1026_coherent_user_range
-       .long   arm1026_flush_kern_dcache_page
+       .long   arm1026_flush_kern_dcache_area
        .long   arm1026_dma_inv_range
        .long   arm1026_dma_clean_range
        .long   arm1026_dma_flush_range
index 2b7c197..471669e 100644 (file)
@@ -207,15 +207,16 @@ ENTRY(arm920_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm920_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(arm920_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -293,7 +294,7 @@ ENTRY(arm920_cache_fns)
        .long   arm920_flush_user_cache_range
        .long   arm920_coherent_kern_range
        .long   arm920_coherent_user_range
-       .long   arm920_flush_kern_dcache_page
+       .long   arm920_flush_kern_dcache_area
        .long   arm920_dma_inv_range
        .long   arm920_dma_clean_range
        .long   arm920_dma_flush_range
index 06a1aa4..ee111b0 100644 (file)
@@ -209,15 +209,16 @@ ENTRY(arm922_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm922_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(arm922_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -295,7 +296,7 @@ ENTRY(arm922_cache_fns)
        .long   arm922_flush_user_cache_range
        .long   arm922_coherent_kern_range
        .long   arm922_coherent_user_range
-       .long   arm922_flush_kern_dcache_page
+       .long   arm922_flush_kern_dcache_area
        .long   arm922_dma_inv_range
        .long   arm922_dma_clean_range
        .long   arm922_dma_flush_range
index cb53435..8deb5bd 100644 (file)
@@ -251,15 +251,16 @@ ENTRY(arm925_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm925_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(arm925_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -346,7 +347,7 @@ ENTRY(arm925_cache_fns)
        .long   arm925_flush_user_cache_range
        .long   arm925_coherent_kern_range
        .long   arm925_coherent_user_range
-       .long   arm925_flush_kern_dcache_page
+       .long   arm925_flush_kern_dcache_area
        .long   arm925_dma_inv_range
        .long   arm925_dma_clean_range
        .long   arm925_dma_flush_range
index 1c48487..64db6e2 100644 (file)
@@ -214,15 +214,16 @@ ENTRY(arm926_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm926_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(arm926_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -309,7 +310,7 @@ ENTRY(arm926_cache_fns)
        .long   arm926_flush_user_cache_range
        .long   arm926_coherent_kern_range
        .long   arm926_coherent_user_range
-       .long   arm926_flush_kern_dcache_page
+       .long   arm926_flush_kern_dcache_area
        .long   arm926_dma_inv_range
        .long   arm926_dma_clean_range
        .long   arm926_dma_flush_range
index 5b0f846..8196b9f 100644 (file)
@@ -141,14 +141,15 @@ ENTRY(arm940_coherent_user_range)
        /* FALLTHROUGH */
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(arm940_flush_kern_dcache_page)
+ENTRY(arm940_flush_kern_dcache_area)
        mov     ip, #0
        mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
 1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
@@ -238,7 +239,7 @@ ENTRY(arm940_cache_fns)
        .long   arm940_flush_user_cache_range
        .long   arm940_coherent_kern_range
        .long   arm940_coherent_user_range
-       .long   arm940_flush_kern_dcache_page
+       .long   arm940_flush_kern_dcache_area
        .long   arm940_dma_inv_range
        .long   arm940_dma_clean_range
        .long   arm940_dma_flush_range
index 40c0449..9a95123 100644 (file)
@@ -183,16 +183,17 @@ ENTRY(arm946_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  * (same as arm926)
  */
-ENTRY(arm946_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(arm946_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -280,7 +281,7 @@ ENTRY(arm946_cache_fns)
        .long   arm946_flush_user_cache_range
        .long   arm946_coherent_kern_range
        .long   arm946_coherent_user_range
-       .long   arm946_flush_kern_dcache_page
+       .long   arm946_flush_kern_dcache_area
        .long   arm946_dma_inv_range
        .long   arm946_dma_clean_range
        .long   arm946_dma_flush_range
index d0d7795..dbc3938 100644 (file)
@@ -226,16 +226,17 @@ ENTRY(feroceon_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
        .align  5
-ENTRY(feroceon_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(feroceon_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -246,7 +247,7 @@ ENTRY(feroceon_flush_kern_dcache_page)
        mov     pc, lr
 
        .align  5
-ENTRY(feroceon_range_flush_kern_dcache_page)
+ENTRY(feroceon_range_flush_kern_dcache_area)
        mrs     r2, cpsr
        add     r1, r0, #PAGE_SZ - CACHE_DLINESIZE      @ top addr is inclusive
        orr     r3, r2, #PSR_I_BIT
@@ -372,7 +373,7 @@ ENTRY(feroceon_cache_fns)
        .long   feroceon_flush_user_cache_range
        .long   feroceon_coherent_kern_range
        .long   feroceon_coherent_user_range
-       .long   feroceon_flush_kern_dcache_page
+       .long   feroceon_flush_kern_dcache_area
        .long   feroceon_dma_inv_range
        .long   feroceon_dma_clean_range
        .long   feroceon_dma_flush_range
@@ -383,7 +384,7 @@ ENTRY(feroceon_range_cache_fns)
        .long   feroceon_flush_user_cache_range
        .long   feroceon_coherent_kern_range
        .long   feroceon_coherent_user_range
-       .long   feroceon_range_flush_kern_dcache_page
+       .long   feroceon_range_flush_kern_dcache_area
        .long   feroceon_range_dma_inv_range
        .long   feroceon_range_dma_clean_range
        .long   feroceon_range_dma_flush_range
index 52b5fd7..9674d36 100644 (file)
@@ -186,15 +186,16 @@ ENTRY(mohawk_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(mohawk_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(mohawk_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
@@ -273,7 +274,7 @@ ENTRY(mohawk_cache_fns)
        .long   mohawk_flush_user_cache_range
        .long   mohawk_coherent_kern_range
        .long   mohawk_coherent_user_range
-       .long   mohawk_flush_kern_dcache_page
+       .long   mohawk_flush_kern_dcache_area
        .long   mohawk_dma_inv_range
        .long   mohawk_dma_clean_range
        .long   mohawk_dma_flush_range
index ac5c800..3e6210b 100644 (file)
@@ -27,8 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
 EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
-EXPORT_SYMBOL(__cpuc_flush_dcache_page);
-EXPORT_SYMBOL(dmac_inv_range);  /* because of flush_ioremap_region() */
+EXPORT_SYMBOL(__cpuc_flush_dcache_area);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
index 5485c82..395cc90 100644 (file)
@@ -254,10 +254,9 @@ __pj4_v6_proc_info:
        .long   0x560f5810
        .long   0xff0ffff0
        .long   PMD_TYPE_SECT | \
-               PMD_SECT_BUFFERABLE | \
-               PMD_SECT_CACHEABLE | \
                PMD_SECT_AP_WRITE | \
-               PMD_SECT_AP_READ
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
index fab134e..96456f5 100644 (file)
@@ -226,15 +226,16 @@ ENTRY(xsc3_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache.
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(xsc3_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(xsc3_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean/invalidate L1 D line
        add     r0, r0, #CACHELINESIZE
        cmp     r0, r1
@@ -309,7 +310,7 @@ ENTRY(xsc3_cache_fns)
        .long   xsc3_flush_user_cache_range
        .long   xsc3_coherent_kern_range
        .long   xsc3_coherent_user_range
-       .long   xsc3_flush_kern_dcache_page
+       .long   xsc3_flush_kern_dcache_area
        .long   xsc3_dma_inv_range
        .long   xsc3_dma_clean_range
        .long   xsc3_dma_flush_range
index f056c28..93df472 100644 (file)
@@ -284,15 +284,16 @@ ENTRY(xscale_coherent_user_range)
        mov     pc, lr
 
 /*
- *     flush_kern_dcache_page(void *page)
+ *     flush_kern_dcache_area(void *addr, size_t size)
  *
  *     Ensure no D cache aliasing occurs, either with itself or
  *     the I cache
  *
- *     - addr  - page aligned address
+ *     - addr  - kernel address
+ *     - size  - region size
  */
-ENTRY(xscale_flush_kern_dcache_page)
-       add     r1, r0, #PAGE_SZ
+ENTRY(xscale_flush_kern_dcache_area)
+       add     r1, r0, r1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
        add     r0, r0, #CACHELINESIZE
@@ -368,7 +369,7 @@ ENTRY(xscale_cache_fns)
        .long   xscale_flush_user_cache_range
        .long   xscale_coherent_kern_range
        .long   xscale_coherent_user_range
-       .long   xscale_flush_kern_dcache_page
+       .long   xscale_flush_kern_dcache_area
        .long   xscale_dma_inv_range
        .long   xscale_dma_clean_range
        .long   xscale_dma_flush_range
@@ -392,7 +393,7 @@ ENTRY(xscale_80200_A0_A1_cache_fns)
        .long   xscale_flush_user_cache_range
        .long   xscale_coherent_kern_range
        .long   xscale_coherent_user_range
-       .long   xscale_flush_kern_dcache_page
+       .long   xscale_flush_kern_dcache_area
        .long   xscale_dma_flush_range
        .long   xscale_dma_clean_range
        .long   xscale_dma_flush_range
index 1dbaa29..635cb18 100644 (file)
@@ -4,7 +4,7 @@
 # Copyright (C) 2001 Russell King
 #
 
-include/asm-arm/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
+include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
        @echo '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index ce319ef..04fef71 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/awk
 #
-# Awk script to generate include/asm-arm/mach-types.h
+# Awk script to generate include/generated/mach-types.h
 #
 BEGIN  { nr = 0 }
 /^#/   { next }
index 07b976d..c3a74ce 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Wed Nov 25 22:14:58 2009
+# Last update: Wed Dec 16 20:06:34 2009
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -1776,6 +1776,7 @@ cybook3                   MACH_CYBOOK3            CYBOOK3                 1784
 wdg002                 MACH_WDG002             WDG002                  1785
 sg560adsl              MACH_SG560ADSL          SG560ADSL               1786
 nextio_n2800_ica       MACH_NEXTIO_N2800_ICA   NEXTIO_N2800_ICA        1787
+dove_db                        MACH_DOVE_DB            DOVE_DB                 1788
 marvell_newdb          MACH_MARVELL_NEWDB      MARVELL_NEWDB           1789
 vandihud               MACH_VANDIHUD           VANDIHUD                1790
 magx_e8                        MACH_MAGX_E8            MAGX_E8                 1791
@@ -2536,3 +2537,44 @@ c3ax03                   MACH_C3AX03             C3AX03                  2549
 mxt_td60               MACH_MXT_TD60           MXT_TD60                2550
 esyx                   MACH_ESYX               ESYX                    2551
 bulldog                        MACH_BULLDOG            BULLDOG                 2553
+derell_me2000          MACH_DERELL_ME2000      DERELL_ME2000           2554
+bcmring_base           MACH_BCMRING_BASE       BCMRING_BASE            2555
+bcmring_evm            MACH_BCMRING_EVM        BCMRING_EVM             2556
+bcmring_evm_jazz       MACH_BCMRING_EVM_JAZZ   BCMRING_EVM_JAZZ        2557
+bcmring_sp             MACH_BCMRING_SP         BCMRING_SP              2558
+bcmring_sv             MACH_BCMRING_SV         BCMRING_SV              2559
+bcmring_sv_jazz                MACH_BCMRING_SV_JAZZ    BCMRING_SV_JAZZ         2560
+bcmring_tablet         MACH_BCMRING_TABLET     BCMRING_TABLET          2561
+bcmring_vp             MACH_BCMRING_VP         BCMRING_VP              2562
+bcmring_evm_seikor     MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR      2563
+bcmring_sp_wqvga       MACH_BCMRING_SP_WQVGA   BCMRING_SP_WQVGA        2564
+bcmring_custom         MACH_BCMRING_CUSTOM     BCMRING_CUSTOM          2565
+acer_s200              MACH_ACER_S200          ACER_S200               2566
+bt270                  MACH_BT270              BT270                   2567
+iseo                   MACH_ISEO               ISEO                    2568
+cezanne                        MACH_CEZANNE            CEZANNE                 2569
+lucca                  MACH_LUCCA              LUCCA                   2570
+supersmart             MACH_SUPERSMART         SUPERSMART              2571
+magnolia2              MACH_MAGNOLIA2          MAGNOLIA2               2573
+emxx                   MACH_EMXX               EMXX                    2574
+outlaw                 MACH_OUTLAW             OUTLAW                  2575
+riot_bei2              MACH_RIOT_BEI2          RIOT_BEI2               2576
+riot_vox               MACH_RIOT_VOX           RIOT_VOX                2577
+riot_x37               MACH_RIOT_X37           RIOT_X37                2578
+mega25mx               MACH_MEGA25MX           MEGA25MX                2579
+benzina2               MACH_BENZINA2           BENZINA2                2580
+ignite                 MACH_IGNITE             IGNITE                  2581
+foggia                 MACH_FOGGIA             FOGGIA                  2582
+arezzo                 MACH_AREZZO             AREZZO                  2583
+leica_skywalker                MACH_LEICA_SKYWALKER    LEICA_SKYWALKER         2584
+jacinto2_jamr          MACH_JACINTO2_JAMR      JACINTO2_JAMR           2585
+gts_nova               MACH_GTS_NOVA           GTS_NOVA                2586
+p3600                  MACH_P3600              P3600                   2587
+dlt2                   MACH_DLT2               DLT2                    2588
+df3120                 MACH_DF3120             DF3120                  2589
+ecucore_9g20           MACH_ECUCORE_9G20       ECUCORE_9G20            2590
+nautel_lpc3240         MACH_NAUTEL_LPC3240     NAUTEL_LPC3240          2591
+glacier                        MACH_GLACIER            GLACIER                 2592
+phrazer_bulldog                MACH_PHRAZER_BULLDOG    PHRAZER_BULLDOG         2593
+omap3_bulldog          MACH_OMAP3_BULLDOG      OMAP3_BULLDOG           2594
+pca101                 MACH_PCA101             PCA101                  2595
diff --git a/arch/avr32/include/asm/asm-offsets.h b/arch/avr32/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/blackfin/include/asm/asm-offsets.h b/arch/blackfin/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 3db478e..76266f8 100644 (file)
@@ -10,7 +10,6 @@
  * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
  * -traditional must not be used when assembling this file.
  */
-#include <linux/autoconf.h>
 #include <arch/memmap.h>
 #include <hwregs/reg_rdwr.h>
 #include <hwregs/intr_vect.h>
diff --git a/arch/cris/include/asm/asm-offsets.h b/arch/cris/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index ddd6fbb..dd7b8e9 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/sched.h>
 #include <asm/thread_info.h>
-#include <linux/autoconf.h>
 
 /*
  * Generate definitions needed by assembly language modules.
index bbfda67..d49d17d 100644 (file)
@@ -8,7 +8,6 @@
  * the kernel has booted.
  */
 
-#include <linux/autoconf.h>
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/page.h>
 
diff --git a/arch/frv/include/asm/asm-offsets.h b/arch/frv/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 55e4fab..75cf7f4 100644 (file)
@@ -10,7 +10,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
diff --git a/arch/h8300/include/asm/asm-offsets.h b/arch/h8300/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index e7cbaa0..475e272 100644 (file)
@@ -103,4 +103,4 @@ archprepare: make_nr_irqs_h FORCE
 PHONY += make_nr_irqs_h FORCE
 
 make_nr_irqs_h: FORCE
-       $(Q)$(MAKE) $(build)=arch/ia64/kernel include/asm-ia64/nr-irqs.h
+       $(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h
diff --git a/arch/ia64/include/asm/asm-offsets.h b/arch/ia64/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 5282546..91b920f 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/cpumask.h>
-#include <asm-ia64/nr-irqs.h>
+#include <generated/nr-irqs.h>
 
 static __inline__ int
 irq_canonicalize (int irq)
index 6b7edca..2a75e93 100644 (file)
@@ -81,17 +81,14 @@ define cmd_nr_irqs
 endef
 
 # We use internal kbuild rules to avoid the "is up to date" message from make
-arch/$(SRCARCH)/kernel/nr-irqs.s: $(srctree)/arch/$(SRCARCH)/kernel/nr-irqs.c \
-                               $(wildcard $(srctree)/include/asm-ia64/*/irq.h)
+arch/$(SRCARCH)/kernel/nr-irqs.s: arch/$(SRCARCH)/kernel/nr-irqs.c
        $(Q)mkdir -p $(dir $@)
        $(call if_changed_dep,cc_s_c)
 
-include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
+include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
        $(Q)mkdir -p $(dir $@)
        $(call cmd,nr_irqs)
 
-clean-files += $(objtree)/include/asm-ia64/nr-irqs.h
-
 #
 # native ivt.S, entry.S and fsys.S
 #
index 0c3564a..9324c87 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/autoconf.h>
 #include <linux/kvm_host.h>
 #include <linux/kbuild.h>
 
diff --git a/arch/m68k/include/asm/asm-offsets.h b/arch/m68k/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 86edb5f..ef54128 100644 (file)
  * for them and trying to understand what they mean.
  *
  * CONFIG_xxx: These are the obvious machine configuration defines created
- * during configuration.  These are defined in include/linux/autoconf.h.
+ * during configuration.  These are defined in autoconf.h.
  *
  * CONSOLE:    There is support for head.S console in this file.  This
  * console can talk to a Mac frame buffer, but could easily be extrapolated
diff --git a/arch/microblaze/include/asm/asm-offsets.h b/arch/microblaze/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index fd7620f..9541171 100644 (file)
@@ -5,9 +5,12 @@ config MIPS
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB
-       # Horrible source of confusion.  Die, die, die ...
-       select EMBEDDED
-       select RTC_LIB if !LEMOTE_FULOONG2E
+       select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       select HAVE_DYNAMIC_FTRACE
+       select HAVE_FTRACE_MCOUNT_RECORD
+       select HAVE_FUNCTION_GRAPH_TRACER
+       select RTC_LIB if !MACH_LOONGSON
 
 mainmenu "Linux/MIPS Kernel Configuration"
 
@@ -22,6 +25,7 @@ choice
 
 config MACH_ALCHEMY
        bool "Alchemy processor based machines"
+       select SYS_SUPPORTS_ZBOOT
 
 config AR7
        bool "Texas Instruments AR7"
@@ -36,6 +40,7 @@ config AR7
        select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_ZBOOT_UART16550
        select GENERIC_GPIO
        select GCD
        select VLYNQ
@@ -43,23 +48,6 @@ config AR7
          Support for the Texas Instruments AR7 System-on-a-Chip
          family: TNETD7100, 7200 and 7300.
 
-config BASLER_EXCITE
-       bool "Basler eXcite smart camera"
-       select CEVT_R4K
-       select CSRC_R4K
-       select DMA_COHERENT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select IRQ_CPU_RM7K
-       select IRQ_CPU_RM9K
-       select MIPS_RM9122
-       select SYS_HAS_CPU_RM9000
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_BIG_ENDIAN
-       help
-         The eXcite is a smart camera platform manufactured by
-         Basler Vision Technologies AG.
-
 config BCM47XX
        bool "BCM47XX based boards"
        select CEVT_R4K
@@ -192,6 +180,7 @@ config LASAT
 
 config MACH_LOONGSON
        bool "Loongson family of machines"
+       select SYS_SUPPORTS_ZBOOT_UART16550
        help
          This enables the support of Loongson family of machines.
 
@@ -233,6 +222,7 @@ config MIPS_MALTA
        select SYS_SUPPORTS_MIPS_CMP
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_SMARTMIPS
+       select SYS_SUPPORTS_ZBOOT
        help
          This enables support for the MIPS Technologies Malta evaluation
          board.
@@ -334,6 +324,24 @@ config PMC_YOSEMITE
          Yosemite is an evaluation board for the RM9000x2 processor
          manufactured by PMC-Sierra.
 
+config POWERTV
+       bool "Cisco PowerTV"
+       select BOOT_ELF32
+       select CEVT_R4K
+       select CPU_MIPSR2_IRQ_VI
+       select CPU_MIPSR2_IRQ_EI
+       select CSRC_POWERTV
+       select DMA_NONCOHERENT
+       select HW_HAS_PCI
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select USB_OHCI_LITTLE_ENDIAN
+       help
+         This enables support for the Cisco PowerTV Platform.
+
 config SGI_IP22
        bool "SGI IP22 (Indy/Indigo2)"
        select ARC
@@ -674,11 +682,11 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
-source "arch/mips/basler/excite/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
+source "arch/mips/powertv/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
 source "arch/mips/txx9/Kconfig"
@@ -778,6 +786,9 @@ config CSRC_BCM1480
 config CSRC_IOASIC
        bool
 
+config CSRC_POWERTV
+       bool
+
 config CSRC_R4K_LIB
        bool
 
@@ -806,20 +817,6 @@ config DMA_NONCOHERENT
 config DMA_NEED_PCI_MAP_STATE
        bool
 
-config EARLY_PRINTK
-       bool "Early printk" if EMBEDDED && DEBUG_KERNEL
-       depends on SYS_HAS_EARLY_PRINTK
-       default y
-       help
-         This option enables special console drivers which allow the kernel
-         to print messages very early in the bootup process.
-
-         This is useful for kernel debugging when your machine crashes very
-         early before the console code is initialized. For normal operation,
-         it is not recommended because it looks ugly on some machines and
-         doesn't cooperate with an X server. You should normally say N here,
-         unless you want to debug such a crash.
-
 config SYS_HAS_EARLY_PRINTK
        bool
 
@@ -1069,6 +1066,21 @@ config CPU_LOONGSON2E
          The Loongson 2E processor implements the MIPS III instruction set
          with many extensions.
 
+         It has an internal FPGA northbridge, which is compatiable to
+         bonito64.
+
+config CPU_LOONGSON2F
+       bool "Loongson 2F"
+       depends on SYS_HAS_CPU_LOONGSON2F
+       select CPU_LOONGSON2
+       help
+         The Loongson 2F processor implements the MIPS III instruction set
+         with many extensions.
+
+         Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller
+         have a similar programming interface with FPGA northbridge used in
+         Loongson2E.
+
 config CPU_MIPS32_R1
        bool "MIPS32 Release 1"
        depends on SYS_HAS_CPU_MIPS32_R1
@@ -1294,6 +1306,16 @@ config CPU_CAVIUM_OCTEON
 
 endchoice
 
+config SYS_SUPPORTS_ZBOOT
+       bool
+       select HAVE_KERNEL_GZIP
+       select HAVE_KERNEL_BZIP2
+       select HAVE_KERNEL_LZMA
+
+config SYS_SUPPORTS_ZBOOT_UART16550
+       bool
+       select SYS_SUPPORTS_ZBOOT
+
 config CPU_LOONGSON2
        bool
        select CPU_SUPPORTS_32BIT_KERNEL
@@ -1303,6 +1325,12 @@ config CPU_LOONGSON2
 config SYS_HAS_CPU_LOONGSON2E
        bool
 
+config SYS_HAS_CPU_LOONGSON2F
+       bool
+       select CPU_SUPPORTS_CPUFREQ
+       select CPU_SUPPORTS_ADDRWINCFG if 64BIT
+       select CPU_SUPPORTS_UNCACHED_ACCELERATED
+
 config SYS_HAS_CPU_MIPS32_R1
        bool
 
@@ -1411,8 +1439,17 @@ config CPU_SUPPORTS_32BIT_KERNEL
        bool
 config CPU_SUPPORTS_64BIT_KERNEL
        bool
+config CPU_SUPPORTS_CPUFREQ
+       bool
+config CPU_SUPPORTS_ADDRWINCFG
+       bool
 config CPU_SUPPORTS_HUGEPAGES
        bool
+config CPU_SUPPORTS_UNCACHED_ACCELERATED
+       bool
+config MIPS_PGD_C0_CONTEXT
+       bool
+       default y if 64BIT && CPU_MIPSR2
 
 #
 # Set to y for ptrace access to watch registers.
@@ -2024,15 +2061,6 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
-config PROBE_INITRD_HEADER
-       bool "Probe initrd header created by addinitrd"
-       depends on BLK_DEV_INITRD
-       help
-         Probe initrd header at the last page of kernel image.
-         Say Y here if you are using arch/mips/boot/addinitrd.c to
-         add initrd or initramfs image to the kernel image.
-         Otherwise, say N.
-
 source "kernel/Kconfig.freezer"
 
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
@@ -2104,6 +2132,7 @@ config MMU
 
 config I8253
        bool
+       select MIPS_EXTERNAL_TIMER
 
 config ZONE_DMA32
        bool
@@ -2180,6 +2209,8 @@ source "kernel/power/Kconfig"
 
 endmenu
 
+source "arch/mips/kernel/cpufreq/Kconfig"
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 364ca89..d2b88a0 100644 (file)
@@ -6,15 +6,66 @@ config TRACE_IRQFLAGS_SUPPORT
 
 source "lib/Kconfig.debug"
 
+config EARLY_PRINTK
+       bool "Early printk" if EMBEDDED
+       depends on SYS_HAS_EARLY_PRINTK
+       default y
+       help
+         This option enables special console drivers which allow the kernel
+         to print messages very early in the bootup process.
+
+         This is useful for kernel debugging when your machine crashes very
+         early before the console code is initialized. For normal operation,
+         it is not recommended because it looks ugly on some machines and
+         doesn't cooperate with an X server. You should normally say N here,
+         unless you want to debug such a crash.
+
+config CMDLINE_BOOL
+       bool "Built-in kernel command line"
+       default n
+       help
+         For most systems, it is firmware or second stage bootloader that
+         by default specifies the kernel command line options.  However,
+         it might be necessary or advantageous to either override the
+         default kernel command line or add a few extra options to it.
+         For such cases, this option allows you to hardcode your own
+         command line options directly into the kernel.  For that, you
+         should choose 'Y' here, and fill in the extra boot arguments
+         in CONFIG_CMDLINE.
+
+         The built-in options will be concatenated to the default command
+         line if CMDLINE_OVERRIDE is set to 'N'. Otherwise, the default
+         command line will be ignored and replaced by the built-in string.
+
+         Most MIPS systems will normally expect 'N' here and rely upon
+         the command line from the firmware or the second-stage bootloader.
+
 config CMDLINE
        string "Default kernel command string"
+       depends on CMDLINE_BOOL
        default ""
        help
          On some platforms, there is currently no way for the boot loader to
-         pass arguments to the kernel. For these platforms, you can supply
-         some command-line options at build time by entering them here.  In
-         other cases you can specify kernel args so that you don't have
-         to set them up in board prom initialization routines.
+         pass arguments to the kernel.  For these platforms, and for the cases
+         when you want to add some extra options to the command line or ignore
+         the default command line, you can supply some command-line options at
+         build time by entering them here.  In other cases you can specify
+         kernel args so that you don't have to set them up in board prom
+         initialization routines.
+
+         For more information, see the CMDLINE_BOOL and CMDLINE_OVERRIDE
+         options.
+
+config CMDLINE_OVERRIDE
+       bool "Built-in command line overrides firware arguments"
+       default n
+       depends on CMDLINE_BOOL
+       help
+         By setting this option to 'Y' you will have your kernel ignore
+         command line arguments from firmware or second stage bootloader.
+         Instead, the built-in command line will be used exclusively.
+
+         Normally, you will choose 'N' here.
 
 config DEBUG_STACK_USAGE
        bool "Enable stack utilization instrumentation"
index 77f5021..1893efd 100644 (file)
@@ -48,7 +48,16 @@ ifneq ($(SUBARCH),$(ARCH))
   endif
 endif
 
+ifndef CONFIG_FUNCTION_TRACER
 cflags-y := -ffunction-sections
+endif
+ifdef CONFIG_FUNCTION_GRAPH_TRACER
+  ifndef KBUILD_MCOUNT_RA_ADDRESS
+    ifeq ($(call cc-option-yn,-mmcount-ra-address), y)
+      cflags-y += -mmcount-ra-address -DKBUILD_MCOUNT_RA_ADDRESS
+    endif
+  endif
+endif
 cflags-y += $(call cc-option, -mno-check-zero-division)
 
 ifdef CONFIG_32BIT
@@ -69,6 +78,7 @@ endif
 
 all-$(CONFIG_BOOT_ELF32)       := $(vmlinux-32)
 all-$(CONFIG_BOOT_ELF64)       := $(vmlinux-64)
+all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlinuz
 
 #
 # GCC uses -G 0 -mabicalls -fpic as default.  We don't want PIC in the kernel
@@ -124,6 +134,8 @@ cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap
 cflags-$(CONFIG_CPU_LOONGSON2E) += \
        $(call cc-option,-march=loongson2e,-march=r4600)
+cflags-$(CONFIG_CPU_LOONGSON2F) += \
+       $(call cc-option,-march=loongson2f,-march=r4600)
 
 cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
                        -Wa,-mips32 -Wa,--trap
@@ -324,6 +336,7 @@ core-$(CONFIG_MACH_LOONGSON) +=arch/mips/loongson/
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \
                     -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) +=0xffffffff80100000
+load-$(CONFIG_LEMOTE_MACH2F) +=0xffffffff80200000
 
 #
 # MIPS Malta board
@@ -331,7 +344,7 @@ load-$(CONFIG_LEMOTE_FULOONG2E) +=0xffffffff80100000
 core-$(CONFIG_MIPS_MALTA)      += arch/mips/mti-malta/
 cflags-$(CONFIG_MIPS_MALTA)    += -I$(srctree)/arch/mips/include/asm/mach-malta
 load-$(CONFIG_MIPS_MALTA)      += 0xffffffff80100000
-all-$(CONFIG_MIPS_MALTA)       := vmlinux.bin
+all-$(CONFIG_MIPS_MALTA)       := vmlinuz.bin
 
 #
 # MIPS SIM
@@ -356,13 +369,6 @@ cflags-$(CONFIG_PMC_YOSEMITE)      += -I$(srctree)/arch/mips/include/asm/mach-yosemit
 load-$(CONFIG_PMC_YOSEMITE)    += 0xffffffff80100000
 
 #
-# Basler eXcite
-#
-core-$(CONFIG_BASLER_EXCITE)   += arch/mips/basler/excite/
-cflags-$(CONFIG_BASLER_EXCITE) += -I$(srctree)/arch/mips/include/asm/mach-excite
-load-$(CONFIG_BASLER_EXCITE)   += 0x80100000
-
-#
 # LASAT platforms
 #
 core-$(CONFIG_LASAT)           += arch/mips/lasat/
@@ -441,6 +447,13 @@ core-$(CONFIG_NEC_MARKEINS)        += arch/mips/emma/markeins/
 load-$(CONFIG_NEC_MARKEINS)    += 0xffffffff88100000
 
 #
+# Cisco PowerTV Platform
+#
+core-$(CONFIG_POWERTV)         += arch/mips/powertv/
+cflags-$(CONFIG_POWERTV)        += -I$(srctree)/arch/mips/include/asm/mach-powertv
+load-$(CONFIG_POWERTV)         += 0xffffffff90800000
+
+#
 # SGI IP22 (Indy/Indigo2)
 #
 # Set the load address to >= 0xffffffff88069000 if you want to leave space for
@@ -581,7 +594,7 @@ load-$(CONFIG_SNI_RM)               += 0xffffffff80600000
 else
 load-$(CONFIG_SNI_RM)          += 0xffffffff80030000
 endif
-all-$(CONFIG_SNI_RM)           := vmlinux.ecoff
+all-$(CONFIG_SNI_RM)           := vmlinuz.ecoff
 
 #
 # Common TXx9
@@ -699,9 +712,23 @@ vmlinux.64: vmlinux
        $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
 
 makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1)
+makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
+          VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1)
 
 all:   $(all-y)
 
+vmlinuz: vmlinux FORCE
+       +@$(call makezboot,$@)
+
+vmlinuz.bin: vmlinux
+       +@$(call makezboot,$@)
+
+vmlinuz.ecoff: vmlinux
+       +@$(call makezboot,$@)
+
+vmlinuz.srec: vmlinux
+       +@$(call makezboot,$@)
+
 vmlinux.bin: $(vmlinux-32)
        +@$(call makeboot,$@)
 
@@ -726,11 +753,13 @@ endif
 
 install:
        $(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+       $(Q)install -D -m 755 vmlinuz $(INSTALL_PATH)/vmlinuz-$(KERNELRELEASE)
        $(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
        $(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
 
 archclean:
        @$(MAKE) $(clean)=arch/mips/boot
+       @$(MAKE) $(clean)=arch/mips/boot/compressed
        @$(MAKE) $(clean)=arch/mips/lasat
 
 define archhelp
@@ -738,10 +767,18 @@ define archhelp
        echo '  vmlinux.ecoff        - ECOFF boot image'
        echo '  vmlinux.bin          - Raw binary boot image'
        echo '  vmlinux.srec         - SREC boot image'
+       echo '  vmlinuz              - Compressed boot(zboot) image'
+       echo '  vmlinuz.ecoff        - ECOFF zboot image'
+       echo '  vmlinuz.bin          - Raw binary zboot image'
+       echo '  vmlinuz.srec         - SREC zboot image'
        echo
        echo '  These will be default as apropriate for a configured platform.'
 endef
 
 CLEAN_FILES += vmlinux.32 \
               vmlinux.64 \
-              vmlinux.ecoff
+              vmlinux.ecoff \
+              vmlinuz \
+              vmlinuz.ecoff \
+              vmlinuz.bin \
+              vmlinuz.srec
index 835f3f0..85169c0 100644 (file)
@@ -505,7 +505,7 @@ static int __init ar7_register_devices(void)
        int res;
        u32 *bootcr, val;
 #ifdef CONFIG_SERIAL_8250
-       static struct uart_port uart_port[2];
+       static struct uart_port uart_port[2] __initdata;
 
        memset(uart_port, 0, sizeof(struct uart_port) * 2);
 
diff --git a/arch/mips/basler/excite/Kconfig b/arch/mips/basler/excite/Kconfig
deleted file mode 100644 (file)
index ba50607..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config BASLER_EXCITE_PROTOTYPE
-       bool "Support for pre-release units"
-       depends on BASLER_EXCITE
-       default n
-       help
-         Pre-series (prototype) units are different from later ones in
-         some ways. Select this option if you have one of these. Please
-         note that a kernel built with this option selected will not be
-         able to run on normal units.
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile
deleted file mode 100644 (file)
index cff29cf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Basler eXcite
-#
-
-obj-$(CONFIG_BASLER_EXCITE)    += excite_irq.o excite_prom.o excite_setup.o \
-                                  excite_device.o excite_procfs.o
-
-obj-m                          += excite_iodev.o
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
deleted file mode 100644 (file)
index e00bc2d..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
-#include <linux/err.h>
-#include <linux/jiffies.h>
-#include <linux/sched.h>
-#include <asm/types.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-#include <rm9k_eth.h>
-#include <rm9k_wdt.h>
-#include <rm9k_xicap.h>
-#include <excite_nandflash.h>
-
-#include "excite_iodev.h"
-
-#define RM9K_GE_UNIT   0
-#define XICAP_UNIT     0
-#define NAND_UNIT      0
-
-#define DLL_TIMEOUT    3               /* seconds */
-
-
-#define RINIT(__start__, __end__, __name__, __parent__) {      \
-       .name   = __name__ "_0",                                \
-       .start  = (__start__),                                  \
-       .end    = (__end__),                                    \
-       .flags  = 0,                                            \
-       .parent = (__parent__)                                  \
-}
-
-#define RINIT_IRQ(__irq__, __name__) { \
-       .name   = __name__ "_0",        \
-       .start  = (__irq__),            \
-       .end    = (__irq__),            \
-       .flags  = IORESOURCE_IRQ,       \
-       .parent = NULL                  \
-}
-
-
-
-enum {
-       slice_xicap,
-       slice_eth
-};
-
-
-
-static struct resource
-       excite_ctr_resource __maybe_unused = {
-               .name           = "GPI counters",
-               .start          = 0,
-               .end            = 5,
-               .flags          = 0,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_gpislice_resource __maybe_unused = {
-               .name           = "GPI slices",
-               .start          = 0,
-               .end            = 1,
-               .flags          = 0,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_mdio_channel_resource __maybe_unused = {
-               .name           = "MDIO channels",
-               .start          = 0,
-               .end            = 1,
-               .flags          = 0,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_fifomem_resource __maybe_unused = {
-               .name           = "FIFO memory",
-               .start          = 0,
-               .end            = 767,
-               .flags          = 0,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_scram_resource __maybe_unused = {
-               .name           = "Scratch RAM",
-               .start          = EXCITE_PHYS_SCRAM,
-               .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
-               .flags          = IORESOURCE_MEM,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_fpga_resource __maybe_unused = {
-               .name           = "System FPGA",
-               .start          = EXCITE_PHYS_FPGA,
-               .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
-               .flags          = IORESOURCE_MEM,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_nand_resource __maybe_unused = {
-               .name           = "NAND flash control",
-               .start          = EXCITE_PHYS_NAND,
-               .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
-               .flags          = IORESOURCE_MEM,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       },
-       excite_titan_resource __maybe_unused = {
-               .name           = "TITAN registers",
-               .start          = EXCITE_PHYS_TITAN,
-               .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
-               .flags          = IORESOURCE_MEM,
-               .parent         = NULL,
-               .sibling        = NULL,
-               .child          = NULL
-       };
-
-
-
-static void adjust_resources(struct resource *res, unsigned int n)
-{
-       struct resource *p;
-       const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
-                                  | IORESOURCE_IRQ | IORESOURCE_DMA;
-
-       for (p = res; p < res + n; p++) {
-               const struct resource * const parent = p->parent;
-               if (parent) {
-                       p->start += parent->start;
-                       p->end   += parent->start;
-                       p->flags =  parent->flags & mask;
-               }
-       }
-}
-
-
-
-#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
-static struct resource xicap_rsrc[] = {
-       RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
-       RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
-       RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
-       RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
-       RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
-       RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
-       RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
-       RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
-       RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
-};
-
-static struct platform_device xicap_pdev = {
-       .name           = XICAP_NAME,
-       .id             = XICAP_UNIT,
-       .num_resources  = ARRAY_SIZE(xicap_rsrc),
-       .resource       = xicap_rsrc
-};
-
-/*
- * Create a platform device for the GPI port that receives the
- * image data from the embedded camera.
- */
-static int __init xicap_devinit(void)
-{
-       unsigned long tend;
-       u32 reg;
-       int retval;
-
-       adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
-
-       /* Power up the slice and configure it. */
-       reg = titan_readl(CPTC1R);
-       reg &= ~(0x11100 << slice_xicap);
-       titan_writel(reg, CPTC1R);
-
-       /* Enable slice & DLL. */
-       reg= titan_readl(CPRR);
-       reg &= ~(0x00030003 << (slice_xicap * 2));
-       titan_writel(reg, CPRR);
-
-       /* Wait for DLLs to lock */
-       tend = jiffies + DLL_TIMEOUT * HZ;
-       while (time_before(jiffies, tend)) {
-               if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
-                       break;
-               yield();
-       }
-
-       if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
-               printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
-                      xicap_pdev.name, DLL_TIMEOUT);
-               retval = -ETIME;
-       } else {
-               /* Register platform device */
-               retval = platform_device_register(&xicap_pdev);
-       }
-
-       return retval;
-}
-
-device_initcall(xicap_devinit);
-#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
-
-
-
-#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
-static struct resource wdt_rsrc[] = {
-       RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
-       RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
-       RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
-};
-
-static struct platform_device wdt_pdev = {
-       .name           = WDT_NAME,
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(wdt_rsrc),
-       .resource       = wdt_rsrc
-};
-
-/*
- * Create a platform device for the GPI port that receives the
- * image data from the embedded camera.
- */
-static int __init wdt_devinit(void)
-{
-       adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
-       return platform_device_register(&wdt_pdev);
-}
-
-device_initcall(wdt_devinit);
-#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
-
-
-
-static struct resource excite_nandflash_rsrc[] = {
-       RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
-};
-
-static struct platform_device excite_nandflash_pdev = {
-       .name           = "excite_nand",
-       .id             = NAND_UNIT,
-       .num_resources  = ARRAY_SIZE(excite_nandflash_rsrc),
-       .resource       = excite_nandflash_rsrc
-};
-
-/*
- * Create a platform device for the access to the nand-flash
- * port
- */
-static int __init excite_nandflash_devinit(void)
-{
-       adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
-
-        /* nothing to be done here */
-
-        /* Register platform device */
-       return platform_device_register(&excite_nandflash_pdev);
-}
-
-device_initcall(excite_nandflash_devinit);
-
-
-
-static struct resource iodev_rsrc[] = {
-       RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
-};
-
-static struct platform_device io_pdev = {
-       .name           = IODEV_NAME,
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(iodev_rsrc),
-       .resource       = iodev_rsrc
-};
-
-/*
- * Create a platform device for the external I/O ports.
- */
-static int __init io_devinit(void)
-{
-       adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
-       return platform_device_register(&io_pdev);
-}
-
-device_initcall(io_devinit);
-
-
-
-
-#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
-static struct resource rm9k_ge_rsrc[] = {
-       RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
-       RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
-       RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
-       RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
-       RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
-       RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
-       RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
-       RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
-       RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
-       RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
-       RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
-       RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
-       RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
-       RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
-       RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
-};
-
-static struct platform_device rm9k_ge_pdev = {
-       .name           = RM9K_GE_NAME,
-       .id             = RM9K_GE_UNIT,
-       .num_resources  = ARRAY_SIZE(rm9k_ge_rsrc),
-       .resource       = rm9k_ge_rsrc
-};
-
-
-
-/*
- * Create a platform device for the Ethernet port.
- */
-static int __init rm9k_ge_devinit(void)
-{
-       u32 reg;
-
-       adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
-
-       /* Power up the slice and configure it. */
-       reg = titan_readl(CPTC1R);
-       reg &= ~(0x11000 << slice_eth);
-       reg |= 0x100 << slice_eth;
-       titan_writel(reg, CPTC1R);
-
-       /* Take the MAC out of reset, reset the DLLs. */
-       reg = titan_readl(CPRR);
-       reg &= ~(0x00030000 << (slice_eth * 2));
-       reg |= 0x3 << (slice_eth * 2);
-       titan_writel(reg, CPRR);
-
-       return platform_device_register(&rm9k_ge_pdev);
-}
-
-device_initcall(rm9k_ge_devinit);
-#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
-
-
-
-static int __init excite_setup_devs(void)
-{
-       int res;
-       u32 reg;
-
-       /* Enable xdma and fifo interrupts */
-       reg = titan_readl(0x0050);
-       titan_writel(reg | 0x18000000, 0x0050);
-
-       res = request_resource(&iomem_resource, &excite_titan_resource);
-       if (res)
-               return res;
-       res = request_resource(&iomem_resource, &excite_scram_resource);
-       if (res)
-               return res;
-       res = request_resource(&iomem_resource, &excite_fpga_resource);
-       if (res)
-               return res;
-       res = request_resource(&iomem_resource, &excite_nand_resource);
-       if (res)
-               return res;
-       excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
-                                  ( IORESOURCE_IO | IORESOURCE_MEM
-                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
-       excite_nand_resource.flags = excite_nand_resource.parent->flags &
-                                  ( IORESOURCE_IO | IORESOURCE_MEM
-                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
-
-       return 0;
-}
-
-arch_initcall(excite_setup_devs);
-
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
deleted file mode 100644 (file)
index 938b1d0..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- *  Copyright (C) 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/compiler.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-
-#include "excite_iodev.h"
-
-
-
-static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
-static int __init iodev_probe(struct platform_device *);
-static int __exit iodev_remove(struct platform_device *);
-static int iodev_open(struct inode *, struct file *);
-static int iodev_release(struct inode *, struct file *);
-static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
-static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
-static irqreturn_t iodev_irqhdl(int, void *);
-
-
-
-static const char iodev_name[] = "iodev";
-static unsigned int iodev_irq;
-static DECLARE_WAIT_QUEUE_HEAD(wq);
-
-
-
-static const struct file_operations fops =
-{
-       .owner          = THIS_MODULE,
-       .open           = iodev_open,
-       .release        = iodev_release,
-       .read           = iodev_read,
-       .poll           = iodev_poll
-};
-
-static struct miscdevice miscdev =
-{
-       .minor          = MISC_DYNAMIC_MINOR,
-       .name           = iodev_name,
-       .fops           = &fops
-};
-
-static struct platform_driver iodev_driver = {
-       .driver = {
-               .name           = iodev_name,
-               .owner          = THIS_MODULE,
-       },
-       .probe          = iodev_probe,
-       .remove         = __devexit_p(iodev_remove),
-};
-
-
-
-static const struct resource *
-iodev_get_resource(struct platform_device *pdv, const char *name,
-                    unsigned int type)
-{
-       char buf[80];
-       if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
-               return NULL;
-       return platform_get_resource_byname(pdv, type, buf);
-}
-
-
-
-/* No hotplugging on the platform bus - use __init */
-static int __init iodev_probe(struct platform_device *dev)
-{
-       const struct resource * const ri =
-               iodev_get_resource(dev, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
-
-       if (unlikely(!ri))
-               return -ENXIO;
-
-       iodev_irq = ri->start;
-       return misc_register(&miscdev);
-}
-
-
-
-static int __exit iodev_remove(struct platform_device *dev)
-{
-       return misc_deregister(&miscdev);
-}
-
-static int iodev_open(struct inode *i, struct file *f)
-{
-       int ret;
-
-       ret = request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
-                          iodev_name, &miscdev);
-
-       return ret;
-}
-
-static int iodev_release(struct inode *i, struct file *f)
-{
-       free_irq(iodev_irq, &miscdev);
-       return 0;
-}
-
-
-
-
-static ssize_t
-iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
-{
-       ssize_t ret;
-       DEFINE_WAIT(w);
-
-       prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
-       if (!signal_pending(current))
-               schedule();
-       ret = signal_pending(current) ? -ERESTARTSYS : 0;
-       finish_wait(&wq, &w);
-       return ret;
-}
-
-
-static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
-{
-       poll_wait(f, &wq, p);
-       return POLLOUT | POLLWRNORM;
-}
-
-static irqreturn_t iodev_irqhdl(int irq, void *ctxt)
-{
-       wake_up(&wq);
-
-       return IRQ_HANDLED;
-}
-
-static int __init iodev_init_module(void)
-{
-       return platform_driver_register(&iodev_driver);
-}
-
-
-
-static void __exit iodev_cleanup_module(void)
-{
-       platform_driver_unregister(&iodev_driver);
-}
-
-module_init(iodev_init_module);
-module_exit(iodev_cleanup_module);
-
-
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
-MODULE_VERSION("0.0");
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h
deleted file mode 100644 (file)
index cbfbb5d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __EXCITE_IODEV_H__
-#define __EXCITE_IODEV_H__
-
-/* Device name */
-#define IODEV_NAME             "iodev"
-
-/* Resource names */
-#define IODEV_RESOURCE_IRQ     "excite_iodev_irq"
-
-#endif /* __EXCITE_IODEV_H__ */
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
deleted file mode 100644 (file)
index 934e0a6..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  Copyright (C) by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslereb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-extern asmlinkage void excite_handle_int(void);
-
-/*
- * Initialize the interrupt handler
- */
-void __init arch_init_irq(void)
-{
-       mips_cpu_irq_init();
-       rm7k_cpu_irq_init();
-       rm9k_cpu_irq_init();
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       const u32
-               interrupts = read_c0_cause() >> 8,
-               mask = ((read_c0_status() >> 8) & 0x000000ff) |
-                      (read_c0_intcontrol() & 0x0000ff00),
-               pending = interrupts & mask;
-       u32 msgintflags, msgintmask, msgint;
-
-       /* process timer interrupt */
-       if (pending & (1 << TIMER_IRQ)) {
-               do_IRQ(TIMER_IRQ);
-               return;
-       }
-
-       /* Process PCI interrupts */
-#if USB_IRQ < 10
-       msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10));
-       msgintmask  = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10));
-       msgint      = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20));
-       if ((pending & (1 << USB_IRQ)) && msgint) {
-#else
-       if (pending & (1 << USB_IRQ)) {
-#endif
-               do_IRQ(USB_IRQ);
-               return;
-       }
-
-       /* Process TITAN interrupts */
-       msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10));
-       msgintmask  = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10));
-       msgint      = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
-       if ((pending & (1 << TITAN_IRQ)) && msgint) {
-               ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
-               do_IRQ(TITAN_IRQ);
-               return;
-       }
-
-       /* Process FPGA line #0 interrupts */
-       msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10));
-       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
-       msgint      = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
-       if ((pending & (1 << FPGA0_IRQ)) && msgint) {
-               do_IRQ(FPGA0_IRQ);
-               return;
-       }
-
-       /* Process FPGA line #1 interrupts */
-       msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10));
-       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
-       msgint      = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
-       if ((pending & (1 << FPGA1_IRQ)) && msgint) {
-               do_IRQ(FPGA1_IRQ);
-               return;
-       }
-
-       /* Process PHY interrupts */
-       msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10));
-       msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
-       msgint      = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
-       if ((pending & (1 << PHY_IRQ)) && msgint) {
-               do_IRQ(PHY_IRQ);
-               return;
-       }
-
-       /* Process spurious interrupts */
-       spurious_interrupt();
-}
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
deleted file mode 100644 (file)
index 08923e6..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  Procfs support for Basler eXcite
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/stat.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-static int excite_unit_id_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%06x", unit_id);
-       return 0;
-}
-
-static int excite_unit_id_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, excite_unit_id_proc_show, NULL);
-}
-
-static const struct file_operations excite_unit_id_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = excite_unit_id_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int
-excite_bootrom_read(char *page, char **start, off_t off, int count,
-                 int *eof, void *data)
-{
-       void __iomem * src;
-
-       if (off >= EXCITE_SIZE_BOOTROM) {
-               *eof = 1;
-               return 0;
-       }
-
-       if ((off + count) > EXCITE_SIZE_BOOTROM)
-               count = EXCITE_SIZE_BOOTROM - off;
-
-       src = ioremap(EXCITE_PHYS_BOOTROM + off, count);
-       if (src) {
-               memcpy_fromio(page, src, count);
-               iounmap(src);
-               *start = page;
-       } else {
-               count = -ENOMEM;
-       }
-
-       return count;
-}
-
-void excite_procfs_init(void)
-{
-       /* Create & populate /proc/excite */
-       struct proc_dir_entry * const pdir = proc_mkdir("excite", NULL);
-       if (pdir) {
-               struct proc_dir_entry * e;
-
-               e = proc_create("unit_id", S_IRUGO, pdir,
-                               &excite_unit_id_proc_fops);
-               if (e) e->size = 6;
-
-               e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
-                                          excite_bootrom_read, NULL);
-               if (e) e->size = EXCITE_SIZE_BOOTROM;
-       }
-}
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c
deleted file mode 100644 (file)
index 68d8bc5..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
- *  Manish Lachwani.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/string.h>
-
-#include <excite.h>
-
-/* This struct is used by Redboot to pass arguments to the kernel */
-typedef struct
-{
-       char *name;
-       char *val;
-} t_env_var;
-
-struct parmblock {
-       t_env_var memsize;
-       t_env_var modetty0;
-       t_env_var ethaddr;
-       t_env_var env_end;
-       char *argv[2];
-       char text[0];
-};
-
-static unsigned int prom_argc;
-static const char ** prom_argv;
-static const t_env_var * prom_env;
-
-static void prom_halt(void) __attribute__((noreturn));
-static void prom_exit(void) __attribute__((noreturn));
-
-
-
-const char *get_system_type(void)
-{
-       return "Basler eXcite";
-}
-
-/*
- * Halt the system
- */
-static void prom_halt(void)
-{
-       printk(KERN_NOTICE "\n** System halted.\n");
-       while (1)
-               asm volatile (
-                       "\t.set\tmips3\n"
-                       "\twait\n"
-                       "\t.set\tmips0\n"
-               );
-}
-
-/*
- * Reset the CPU and re-enter Redboot
- */
-static void prom_exit(void)
-{
-       unsigned int i;
-       volatile unsigned char * const flg =
-               (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);
-
-       /* Clear the watchdog reset flag, set the reboot flag */
-       *flg &= ~0x01;
-       *flg |= 0x80;
-
-       for (i = 0; i < 10; i++) {
-               *(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
-               iob();
-               mdelay(1000);
-       }
-
-       printk(KERN_NOTICE "Reset failed\n");
-       prom_halt();
-}
-
-static const char __init *prom_getenv(char *name)
-{
-       const t_env_var * p;
-       for (p = prom_env; p->name != NULL; p++)
-               if(strcmp(name, p->name) == 0)
-                       break;
-       return p->val;
-}
-
-/*
- * Init routine which accepts the variables from Redboot
- */
-void __init prom_init(void)
-{
-       const struct parmblock * const pb = (struct parmblock *) fw_arg2;
-
-       prom_argc = fw_arg0;
-       prom_argv = (const char **) fw_arg1;
-       prom_env = &pb->memsize;
-
-       /* Callbacks for halt, restart */
-       _machine_restart = (void (*)(char *)) prom_exit;
-       _machine_halt = prom_halt;
-
-#ifdef CONFIG_32BIT
-       /* copy command line */
-       strcpy(arcs_cmdline, prom_argv[1]);
-       memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
-       strcpy(modetty, prom_getenv("modetty0"));
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-#      error 64 bit support not implemented
-#endif /* CONFIG_64BIT */
-}
-
-/* This is called from free_initmem(), so we need to provide it */
-void __init prom_free_prom_memory(void)
-{
-       /* Nothing to do */
-}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
deleted file mode 100644 (file)
index d66b3b8..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
- *  Manish Lachwani.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/pgtable-32.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-#define TITAN_UART_CLK 25000000
-
-#if 1
-/* normal serial port assignment */
-#define REGBASE_SER0   0x0208
-#define REGBASE_SER1   0x0238
-#define MASK_SER0      0x1
-#define MASK_SER1      0x2
-#else
-/* serial ports swapped */
-#define REGBASE_SER0   0x0238
-#define REGBASE_SER1   0x0208
-#define MASK_SER0      0x2
-#define MASK_SER1      0x1
-#endif
-
-unsigned long memsize;
-char modetty[30];
-unsigned int titan_irq = TITAN_IRQ;
-static void __iomem * ctl_regs;
-u32 unit_id;
-
-volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD);
-volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN);
-
-/* Protect access to shared GPI registers */
-DEFINE_SPINLOCK(titan_lock);
-int titan_irqflags;
-
-
-/*
- * The eXcite platform uses the alternate timer interrupt
- *
- * Fixme: At the time of this writing cevt-r4k.c doesn't yet know about how
- * to handle the alternate timer interrupt of the RM9000.
- */
-void __init plat_time_init(void)
-{
-       const u32 modebit5 = ocd_readl(0x00e4);
-       unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2;
-       unsigned int div = ((modebit5 >> 16) & 0x1f) + 2;
-
-       if (div == 33)
-               div = 1;
-       mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
-}
-
-static int __init excite_init_console(void)
-{
-#if defined(CONFIG_SERIAL_8250)
-       static __initdata char serr[] =
-               KERN_ERR "Serial port #%u setup failed\n";
-       struct uart_port up;
-
-       /* Take the DUART out of reset */
-       titan_writel(0x00ff1cff, CPRR);
-
-#if (CONFIG_SERIAL_8250_NR_UARTS > 1)
-       /* Enable both ports */
-       titan_writel(MASK_SER0 | MASK_SER1, UACFG);
-#else
-       /* Enable port #0 only */
-       titan_writel(MASK_SER0, UACFG);
-#endif
-
-       /*
-        * Set up serial port #0. Do not use autodetection; the result is
-        * not what we want.
-        */
-       memset(&up, 0, sizeof(up));
-       up.membase      = (char *) titan_addr(REGBASE_SER0);
-       up.irq          = TITAN_IRQ;
-       up.uartclk      = TITAN_UART_CLK;
-       up.regshift     = 0;
-       up.iotype       = UPIO_RM9000;
-       up.type         = PORT_RM9000;
-       up.flags        = UPF_SHARE_IRQ;
-       up.line         = 0;
-       if (early_serial_setup(&up))
-               printk(serr, up.line);
-
-#if CONFIG_SERIAL_8250_NR_UARTS > 1
-       /* And now for port #1. */
-       up.membase      = (char *) titan_addr(REGBASE_SER1);
-       up.line         = 1;
-       if (early_serial_setup(&up))
-               printk(serr, up.line);
-#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */
-#else
-       /* Leave the DUART in reset */
-       titan_writel(0x00ff3cff, CPRR);
-#endif  /* defined(CONFIG_SERIAL_8250) */
-
-       return 0;
-}
-
-static int __init excite_platform_init(void)
-{
-       unsigned int i;
-       unsigned char buf[3];
-       u8 reg;
-       void __iomem * dpr;
-
-       /* BIU buffer allocations */
-       ocd_writel(8, CPURSLMT);        /* CPU */
-       titan_writel(4, CPGRWL);        /* GPI / Ethernet */
-
-       /* Map control registers located in FPGA */
-       ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16);
-       if (!ctl_regs)
-               panic("eXcite: failed to map platform control registers\n");
-       memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf));
-       unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16);
-
-       /* Clear the reboot flag */
-       dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1);
-       reg = __raw_readb(dpr);
-       __raw_writeb(reg & 0x7f, dpr);
-       iounmap(dpr);
-
-       /* Interrupt controller setup */
-       for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) {
-               ocd_writel(0x00000000, i + 0x04);
-               ocd_writel(0xffffffff, i + 0x0c);
-       }
-       ocd_writel(0x2, NMICONFIG);
-
-       ocd_writel(0x1 << (TITAN_MSGINT % 0x20),
-                  INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20)));
-       ocd_writel((0x1 << (FPGA0_MSGINT % 0x20))
-                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))),
-                  INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20)));
-       ocd_writel((0x1 << (FPGA1_MSGINT % 0x20))
-                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))),
-                  INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20)));
-       ocd_writel((0x1 << (PHY_MSGINT % 0x20))
-                  | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))),
-                  INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20)));
-#if USB_IRQ < 10
-       ocd_writel((0x1 << (USB_MSGINT % 0x20))
-                  | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))),
-                  INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20)));
-#endif
-       /* Enable the packet FIFO, XDMA and XDMA arbiter */
-       titan_writel(0x00ff18ff, CPRR);
-
-       /*
-        * Set up the PADMUX. Power down all ethernet slices,
-        * they will be powered up and configured at device startup.
-        */
-       titan_writel(0x00878206, CPTC1R);
-       titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */
-
-       /* Reset and enable the FIFO block */
-       titan_writel(0x00000001, SDRXFCIE);
-       titan_writel(0x00000001, SDTXFCIE);
-       titan_writel(0x00000100, SDRXFCIE);
-       titan_writel(0x00000000, SDTXFCIE);
-
-       /*
-        * Initialize the common interrupt shared by all components of
-        * the GPI/Ethernet subsystem.
-        */
-       titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0);
-       titan_writel(TITAN_MSGINT, CPCFG1);
-
-       /*
-        * XDMA configuration.
-        * In order for the XDMA to be sharable among multiple drivers,
-        * the setup must be done here in the platform. The reason is that
-        * this setup can only be done while the XDMA is in reset. If this
-        * were done in a driver, it would interrupt all other drivers
-        * using the XDMA.
-        */
-       titan_writel(0x80021dff, GXCFG);        /* XDMA reset */
-       titan_writel(0x00000000, CPXCISRA);
-       titan_writel(0x00000000, CPXCISRB);     /* clear pending interrupts */
-#if defined(CONFIG_HIGHMEM)
-#      error change for HIGHMEM support!
-#else
-       titan_writel(0x00000000, GXDMADRPFX);   /* buffer address prefix */
-#endif
-       titan_writel(0, GXDMA_DESCADR);
-
-       for (i = 0x5040; i <= 0x5300; i += 0x0040)
-               titan_writel(0x80080000, i);    /* reset channel */
-
-       titan_writel((0x1 << 29)                        /* no sparse tx descr. */
-                    | (0x1 << 28)                      /* no sparse rx descr. */
-                    | (0x1 << 23) | (0x1 << 24)        /* descriptor coherency */
-                    | (0x1 << 21) | (0x1 << 22)        /* data coherency */
-                    | (0x1 << 17)
-                    | 0x1dff,
-                    GXCFG);
-
-#if defined(CONFIG_SMP)
-#      error No SMP support
-#else
-       /* All interrupts go to core #0 only. */
-       titan_writel(0x1f007fff, CPDST0A);
-       titan_writel(0x00000000, CPDST0B);
-       titan_writel(0x0000ff3f, CPDST1A);
-       titan_writel(0x00000000, CPDST1B);
-       titan_writel(0x00ffffff, CPXDSTA);
-       titan_writel(0x00000000, CPXDSTB);
-#endif
-
-       /* Enable DUART interrupts, disable everything else. */
-       titan_writel(0x04000000, CPGIG0ER);
-       titan_writel(0x000000c0, CPGIG1ER);
-
-       excite_procfs_init();
-       return 0;
-}
-
-void __init plat_mem_setup(void)
-{
-       volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000;
-
-       /* Announce RAM to system */
-       add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
-
-       /* Set up the peripheral address map */
-       *(boot_ocd_base + (LKB9 / sizeof(u32))) = 0;
-       *(boot_ocd_base + (LKB10 / sizeof(u32))) = 0;
-       *(boot_ocd_base + (LKB11 / sizeof(u32))) = 0;
-       *(boot_ocd_base + (LKB12 / sizeof(u32))) = 0;
-       wmb();
-       *(boot_ocd_base + (LKB0 / sizeof(u32))) = EXCITE_PHYS_OCD >> 4;
-       wmb();
-
-       ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5);
-       ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5);
-       ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13);
-       ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13);
-
-       /* Local bus slot #0 */
-       ocd_writel(0x00040510, LDP0);
-       ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9);
-       ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9);
-
-       /* Local bus slot #2 */
-       ocd_writel(0x00000330, LDP2);
-       ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11);
-       ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11);
-
-       /* Local bus slot #3 */
-       ocd_writel(0x00123413, LDP3);
-       ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12);
-       ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12);
-}
-
-
-
-console_initcall(excite_init_console);
-arch_initcall(excite_platform_init);
-
-EXPORT_SYMBOL(titan_lock);
-EXPORT_SYMBOL(titan_irqflags);
-EXPORT_SYMBOL(titan_irq);
-EXPORT_SYMBOL(ocd_base);
-EXPORT_SYMBOL(titan_base);
index fb284c3..c51405e 100644 (file)
@@ -100,11 +100,11 @@ static __init void prom_init_console(void)
 
 static __init void prom_init_cmdline(void)
 {
-       static char buf[CL_SIZE] __initdata;
+       static char buf[COMMAND_LINE_SIZE] __initdata;
 
        /* Get the kernel command line from CFE */
-       if (cfe_getenv("LINUX_CMDLINE", buf, CL_SIZE) >= 0) {
-               buf[CL_SIZE-1] = 0;
+       if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
+               buf[COMMAND_LINE_SIZE - 1] = 0;
                strcpy(arcs_cmdline, buf);
        }
 
@@ -112,13 +112,13 @@ static __init void prom_init_cmdline(void)
         * as CFE is not available anymore later in the boot process. */
        if ((strstr(arcs_cmdline, "console=")) == NULL) {
                /* Try to read the default serial port used by CFE */
-               if ((cfe_getenv("BOOT_CONSOLE", buf, CL_SIZE) < 0)
+               if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
                    || (strncmp("uart", buf, 4)))
                        /* Default to uart0 */
                        strcpy(buf, "uart0");
 
                /* Compute the new command line */
-               snprintf(arcs_cmdline, CL_SIZE, "%s console=ttyS%c,115200",
+               snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
                         arcs_cmdline, buf[4]);
        }
 }
index 2a209d7..094bc84 100644 (file)
@@ -25,7 +25,7 @@ strip-flags   = $(addprefix --remove-section=,$(drop-sections))
 
 VMLINUX = vmlinux
 
-all: vmlinux.ecoff vmlinux.srec addinitrd
+all: vmlinux.ecoff vmlinux.srec
 
 vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX)
        $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS)
@@ -39,11 +39,7 @@ vmlinux.bin: $(VMLINUX)
 vmlinux.srec: $(VMLINUX)
        $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec
 
-$(obj)/addinitrd: $(obj)/addinitrd.c
-       $(HOSTCC) -o $@ $^
-
-clean-files += addinitrd \
-              elf2ecoff \
+clean-files += elf2ecoff \
               vmlinux.bin \
               vmlinux.ecoff \
               vmlinux.srec
diff --git a/arch/mips/boot/addinitrd.c b/arch/mips/boot/addinitrd.c
deleted file mode 100644 (file)
index b5b3feb..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * addinitrd - program to add a initrd image to an ecoff kernel
- *
- * (C) 1999 Thomas Bogendoerfer
- * minor modifications, cleanup: Guido Guenther <agx@sigxcpu.org>
- * further cleanup: Maciej W. Rozycki
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <netinet/in.h>
-
-#include "ecoff.h"
-
-#define MIPS_PAGE_SIZE 4096
-#define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1)
-
-#define swab16(x) \
-        ((unsigned short)( \
-                (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
-                (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
-
-#define swab32(x) \
-        ((unsigned int)( \
-                (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
-                (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
-                (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
-                (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
-
-#define SWAB(a)        (swab ? swab32(a) : (a))
-
-void die(char *s)
-{
-       perror(s);
-       exit(1);
-}
-
-int main(int argc, char *argv[])
-{
-       int fd_vmlinux, fd_initrd, fd_outfile;
-       FILHDR efile;
-       AOUTHDR eaout;
-       SCNHDR esecs[3];
-       struct stat st;
-       char buf[1024];
-       unsigned long loadaddr;
-       unsigned long initrd_header[2];
-       int i, cnt;
-       int swab = 0;
-
-       if (argc != 4) {
-               printf("Usage: %s <vmlinux> <initrd> <outfile>\n", argv[0]);
-               exit(1);
-       }
-
-       if ((fd_vmlinux = open (argv[1], O_RDONLY)) < 0)
-                die("open vmlinux");
-       if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile)
-               die("read file header");
-       if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout)
-               die("read aout header");
-       if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs)
-               die("read section headers");
-       /*
-        * check whether the file is good for us
-        */
-       /* TBD */
-
-       /*
-        * check, if we have to swab words
-        */
-       if (ntohs(0xaa55) == 0xaa55) {
-               if (efile.f_magic == swab16(MIPSELMAGIC))
-                       swab = 1;
-       } else {
-               if (efile.f_magic == swab16(MIPSEBMAGIC))
-                       swab = 1;
-       }
-
-       /* make sure we have an empty data segment for the initrd */
-       if (eaout.dsize || esecs[1].s_size) {
-               fprintf(stderr, "Data segment not empty. Giving up!\n");
-               exit(1);
-       }
-       if ((fd_initrd = open (argv[2], O_RDONLY)) < 0)
-               die("open initrd");
-       if (fstat (fd_initrd, &st) < 0)
-               die("fstat initrd");
-       loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)
-                       + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8;
-       if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)))
-               loadaddr += MIPS_PAGE_SIZE;
-       initrd_header[0] = SWAB(0x494E5244);
-       initrd_header[1] = SWAB(st.st_size);
-       eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8);
-       eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr);
-
-       if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
-               die("open outfile");
-       if (write (fd_outfile, &efile, sizeof efile) != sizeof efile)
-               die("write file header");
-       if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout)
-               die("write aout header");
-       if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs)
-               die("write section headers");
-       /* skip padding */
-       if(lseek(fd_vmlinux, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
-               die("lseek vmlinux");
-       if(lseek(fd_outfile, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
-               die("lseek outfile");
-       /* copy text segment */
-       cnt = SWAB(eaout.tsize);
-       while (cnt) {
-               if ((i = read (fd_vmlinux, buf, sizeof buf)) <= 0)
-                       die("read vmlinux");
-               if (write (fd_outfile, buf, i) != i)
-                       die("write vmlinux");
-               cnt -= i;
-       }
-       if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header)
-               die("write initrd header");
-       while ((i = read (fd_initrd, buf, sizeof buf)) > 0)
-               if (write (fd_outfile, buf, i) != i)
-                       die("write initrd");
-       close(fd_vmlinux);
-       close(fd_initrd);
-       return 0;
-}
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
new file mode 100644 (file)
index 0000000..e27f40b
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.
+#
+# Adapted for MIPS Pete Popov, Dan Malek
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+# Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University
+# Author: Wu Zhangjin <wuzj@lemote.com>
+#
+
+# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
+VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
+VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
+VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" ] && printf %x $$(($(VMLINUX_LOAD_ADDRESS) + $(VMLINUX_SIZE))))
+
+# set the default size of the mallocing area for decompressing
+BOOT_HEAP_SIZE := 0x400000
+
+# Disable Function Tracer
+KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")
+
+KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \
+       -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \
+
+KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
+       -DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) \
+       -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE)
+
+obj-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o
+
+obj-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
+
+OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
+$(obj)/vmlinux.bin: $(KBUILD_IMAGE)
+       $(call if_changed,objcopy)
+
+suffix_$(CONFIG_KERNEL_GZIP)  = gz
+suffix_$(CONFIG_KERNEL_BZIP2) = bz2
+suffix_$(CONFIG_KERNEL_LZMA)  = lzma
+tool_$(CONFIG_KERNEL_GZIP)    = gzip
+tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
+tool_$(CONFIG_KERNEL_LZMA)    = lzma
+$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin
+       $(call if_changed,$(tool_y))
+
+$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o
+       $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \
+               --add-section=.image=$< \
+               --set-section-flags=.image=contents,alloc,load,readonly,data \
+               $(obj)/dummy.o $@
+
+LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
+vmlinuz: $(src)/ld.script $(obj-y) $(obj)/piggy.o
+       $(call if_changed,ld)
+       $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap $@
+
+#
+# Some DECstations need all possible sections of an ECOFF executable
+#
+ifdef CONFIG_MACH_DECSTATION
+  E2EFLAGS = -a
+else
+  E2EFLAGS =
+endif
+
+# elf2ecoff can only handle 32bit image
+
+ifdef CONFIG_32BIT
+       VMLINUZ = vmlinuz
+else
+       VMLINUZ = vmlinuz.32
+endif
+
+vmlinuz.32: vmlinuz
+       $(Q)$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
+
+vmlinuz.ecoff: $(obj)/../elf2ecoff $(VMLINUZ)
+       $(Q)$(obj)/../elf2ecoff $(VMLINUZ) vmlinuz.ecoff $(E2EFLAGS)
+
+$(obj)/../elf2ecoff: $(src)/../elf2ecoff.c
+       $(Q)$(HOSTCC) -o $@ $^
+
+drop-sections  = .reginfo .mdebug .comment .note .pdr .options .MIPS.options
+strip-flags    = $(addprefix --remove-section=,$(drop-sections))
+
+OBJCOPYFLAGS_vmlinuz.bin := $(OBJCOPYFLAGS) -O binary $(strip-flags)
+vmlinuz.bin: vmlinuz
+       $(call if_changed,objcopy)
+
+OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec $(strip-flags)
+vmlinuz.srec: vmlinuz
+       $(call if_changed,objcopy)
+
+clean:
+clean-files += *.o \
+              vmlinu*
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
new file mode 100644 (file)
index 0000000..ff4dc7a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * MIPS-specific debug support for pre-boot environment
+ *
+ * NOTE: putc() is board specific, if your board have a 16550 compatible uart,
+ * please select SYS_SUPPORTS_ZBOOT_UART16550 for your machine. othewise, you
+ * need to implement your own putc().
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+void __attribute__ ((weak)) putc(char c)
+{
+}
+
+void puts(const char *s)
+{
+       char c;
+       while ((c = *s++) != '\0') {
+               putc(c);
+               if (c == '\n')
+                       putc('\r');
+       }
+}
+
+void puthex(unsigned long long val)
+{
+
+       unsigned char buf[10];
+       int i;
+       for (i = 7; i >= 0; i--) {
+               buf[i] = "0123456789ABCDEF"[val & 0x0F];
+               val >>= 4;
+       }
+       buf[8] = '\0';
+       puts(buf);
+}
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
new file mode 100644 (file)
index 0000000..67330c2
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Misc. bootloader code for many machines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Matt Porter <mporter@mvista.com> Derived from
+ * arch/ppc/boot/prep/misc.c
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/addrspace.h>
+
+/* These two variables specify the free mem region
+ * that can be used for temporary malloc area
+ */
+unsigned long free_mem_ptr;
+unsigned long free_mem_end_ptr;
+char *zimage_start;
+
+/* The linker tells us where the image is. */
+extern unsigned char __image_begin, __image_end;
+extern unsigned char __ramdisk_begin, __ramdisk_end;
+unsigned long initrd_size;
+
+/* debug interfaces  */
+extern void puts(const char *s);
+extern void puthex(unsigned long long val);
+
+void error(char *x)
+{
+       puts("\n\n");
+       puts(x);
+       puts("\n\n -- System halted");
+
+       while (1)
+               ;       /* Halt */
+}
+
+/* activate the code for pre-boot environment */
+#define STATIC static
+
+#ifdef CONFIG_KERNEL_GZIP
+void *memcpy(void *dest, const void *src, size_t n)
+{
+       int i;
+       const char *s = src;
+       char *d = dest;
+
+       for (i = 0; i < n; i++)
+               d[i] = s[i];
+       return dest;
+}
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+void *memset(void *s, int c, size_t n)
+{
+       int i;
+       char *ss = s;
+
+       for (i = 0; i < n; i++)
+               ss[i] = c;
+       return s;
+}
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+void decompress_kernel(unsigned long boot_heap_start)
+{
+       int zimage_size;
+
+       /*
+        * We link ourself to an arbitrary low address.  When we run, we
+        * relocate outself to that address.  __image_beign points to
+        * the part of the image where the zImage is. -- Tom
+        */
+       zimage_start = (char *)(unsigned long)(&__image_begin);
+       zimage_size = (unsigned long)(&__image_end) -
+           (unsigned long)(&__image_begin);
+
+       /*
+        * The zImage and initrd will be between start and _end, so they've
+        * already been moved once.  We're good to go now. -- Tom
+        */
+       puts("zimage at:     ");
+       puthex((unsigned long)zimage_start);
+       puts(" ");
+       puthex((unsigned long)(zimage_size + zimage_start));
+       puts("\n");
+
+       if (initrd_size) {
+               puts("initrd at:     ");
+               puthex((unsigned long)(&__ramdisk_begin));
+               puts(" ");
+               puthex((unsigned long)(&__ramdisk_end));
+               puts("\n");
+       }
+
+       /* this area are prepared for mallocing when decompressing */
+       free_mem_ptr = boot_heap_start;
+       free_mem_end_ptr = boot_heap_start + BOOT_HEAP_SIZE;
+
+       /* Display standard Linux/MIPS boot prompt for kernel args */
+       puts("Uncompressing Linux at load address ");
+       puthex(VMLINUX_LOAD_ADDRESS_ULL);
+       puts("\n");
+       /* Decompress the kernel with according algorithm */
+       decompress(zimage_start, zimage_size, 0, 0,
+                  (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);
+       /* FIXME: is there a need to flush cache here? */
+       puts("Now, booting the kernel...\n");
+}
diff --git a/arch/mips/boot/compressed/dummy.c b/arch/mips/boot/compressed/dummy.c
new file mode 100644 (file)
index 0000000..31dbf45
--- /dev/null
@@ -0,0 +1,4 @@
+int main(void)
+{
+       return 0;
+}
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
new file mode 100644 (file)
index 0000000..4e65a84
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * Written by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1995 - 1999 Ralf Baechle
+ * Copyright (C) 1996 Paul M. Antoine
+ * Modified for DECStation and hence R3000 support by Paul M. Antoine
+ * Further modifications by David S. Miller and Harald Koerfgen
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+       .set noreorder
+       .cprestore
+       LEAF(start)
+start:
+       /* Save boot rom start args */
+       move    s0, a0
+       move    s1, a1
+       move    s2, a2
+       move    s3, a3
+
+       /* Clear BSS */
+       PTR_LA  a0, _edata
+       PTR_LA  a2, _end
+1:     sw      zero, 0(a0)
+       bne     a2, a0, 1b
+        addiu  a0, a0, 4
+
+       PTR_LA  a0, (.heap)          /* heap address */
+       PTR_LA  sp, (.stack + 8192)  /* stack address */
+
+       PTR_LA  ra, 2f
+       PTR_LA  k0, decompress_kernel
+       jr      k0
+        nop
+2:
+       move    a0, s0
+       move    a1, s1
+       move    a2, s2
+       move    a3, s3
+       PTR_LI  k0, KERNEL_ENTRY
+       jr      k0
+        nop
+3:
+       b       3b
+        nop
+       END(start)
+
+       .comm .heap,BOOT_HEAP_SIZE,4
+       .comm .stack,4096*2,4
diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script
new file mode 100644 (file)
index 0000000..29e9f4c
--- /dev/null
@@ -0,0 +1,150 @@
+OUTPUT_ARCH(mips)
+ENTRY(start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  .init          : { *(.init)          } =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);               /* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___dbe_table = .;     /* Exception table for data bus errors */
+  __dbe_table : { *(__dbe_table) }
+  __stop___dbe_table = .;
+
+  __start___ksymtab = .;       /* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;
+
+  . = ALIGN(8192);
+  .data.init_task : { *(.data.init_task) }
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);     /* Align double page for init_task_union */
+  __init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+
+   /* Put the compressed image here, so bss is on the end. */
+   __image_begin = .;
+   *(.image)
+   __image_end = .;
+   /* Align the initial ramdisk image (INITRD) on page boundaries. */
+   . = ALIGN(4096);
+   __ramdisk_begin = .;
+   *(.initrd)
+   __ramdisk_end = .;
+   . = ALIGN(4096);
+
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __bss_start = .;
+  _fbss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   .  = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+  }
+
+  /* Sections to be discarded */
+  /DISCARD/ :
+  {
+        *(.text.exit)
+        *(.data.exit)
+        *(.exitcall.exit)
+  }
+
+  /* This is the MIPS specific mdebug section.  */
+  .mdebug : { *(.mdebug) }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+  .comment : { *(.comment) }
+  .note : { *(.note) }
+}
diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c
new file mode 100644 (file)
index 0000000..c9caaf4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 16550 compatible uart based serial debug support for zboot
+ */
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+
+#if defined(CONFIG_MACH_LOONGSON) || defined(CONFIG_MIPS_MALTA)
+#define UART_BASE 0x1fd003f8
+#define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset))
+#endif
+
+#ifdef CONFIG_AR7
+#include <ar7.h>
+#define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
+#endif
+
+#ifndef PORT
+#error please define the serial port address for your own machine
+#endif
+
+static inline unsigned int serial_in(int offset)
+{
+       return *((char *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+       *((char *)PORT(offset)) = value;
+}
+
+void putc(char c)
+{
+       int timeout = 1024;
+
+       while (((serial_in(UART_LSR) & UART_LSR_THRE) == 0) && (timeout-- > 0))
+               ;
+
+       serial_out(UART_TX, c);
+}
index 1394362..3e98763 100644 (file)
@@ -9,7 +9,7 @@
 # Copyright (C) 2005-2009 Cavium Networks
 #
 
-obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
+obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
 obj-y += dma-octeon.o flash_setup.o
 obj-y += octeon-memcpy.o
 
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c
new file mode 100644 (file)
index 0000000..b6df538
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/irqflags.h>
+#include <linux/notifier.h>
+#include <linux/prefetch.h>
+#include <linux/sched.h>
+
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/octeon/octeon.h>
+
+static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
+       void *data)
+{
+       unsigned long flags;
+       unsigned int status;
+
+       switch (action) {
+       case CU2_EXCEPTION:
+               prefetch(&current->thread.cp2);
+               local_irq_save(flags);
+               KSTK_STATUS(current) |= ST0_CU2;
+               status = read_c0_status();
+               write_c0_status(status | ST0_CU2);
+               octeon_cop2_restore(&(current->thread.cp2));
+               write_c0_status(status & ~ST0_CU2);
+               local_irq_restore(flags);
+
+               return NOTIFY_BAD;      /* Don't call default notifier */
+       }
+
+       return NOTIFY_OK;               /* Let default notifier send signals */
+}
+
+static struct notifier_block cnmips_cu2_notifier = {
+       .notifier_call = cnmips_cu2_call,
+};
+
+static int cnmips_cu2_setup(void)
+{
+       return register_cu2_notifier(&cnmips_cu2_notifier);
+}
+early_initcall(cnmips_cu2_setup);
index be711dd..cfdb4c2 100644 (file)
@@ -159,6 +159,94 @@ out:
 }
 device_initcall(octeon_rng_device_init);
 
+/* Octeon SMI/MDIO interface.  */
+static int __init octeon_mdiobus_device_init(void)
+{
+       struct platform_device *pd;
+       int ret = 0;
+
+       if (octeon_is_simulation())
+               return 0; /* No mdio in the simulator. */
+
+       /* The bus number is the platform_device id.  */
+       pd = platform_device_alloc("mdio-octeon", 0);
+       if (!pd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = platform_device_add(pd);
+       if (ret)
+               goto fail;
+
+       return ret;
+fail:
+       platform_device_put(pd);
+
+out:
+       return ret;
+
+}
+device_initcall(octeon_mdiobus_device_init);
+
+/* Octeon mgmt port Ethernet interface.  */
+static int __init octeon_mgmt_device_init(void)
+{
+       struct platform_device *pd;
+       int ret = 0;
+       int port, num_ports;
+
+       struct resource mgmt_port_resource = {
+               .flags  = IORESOURCE_IRQ,
+               .start  = -1,
+               .end    = -1
+       };
+
+       if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
+               return 0;
+
+       if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+               num_ports = 1;
+       else
+               num_ports = 2;
+
+       for (port = 0; port < num_ports; port++) {
+               pd = platform_device_alloc("octeon_mgmt", port);
+               if (!pd) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               switch (port) {
+               case 0:
+                       mgmt_port_resource.start = OCTEON_IRQ_MII0;
+                       break;
+               case 1:
+                       mgmt_port_resource.start = OCTEON_IRQ_MII1;
+                       break;
+               default:
+                       BUG();
+               }
+               mgmt_port_resource.end = mgmt_port_resource.start;
+
+               ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
+
+               if (ret)
+                       goto fail;
+
+               ret = platform_device_add(pd);
+               if (ret)
+                       goto fail;
+       }
+       return ret;
+fail:
+       platform_device_put(pd);
+
+out:
+       return ret;
+
+}
+device_initcall(octeon_mgmt_device_init);
+
 MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Platform driver for Octeon SOC");
index 3564830..5a5b6ba 100644 (file)
@@ -10,7 +10,6 @@ CONFIG_MIPS=y
 #
 # CONFIG_MACH_ALCHEMY is not set
 CONFIG_AR7=y
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -265,7 +264,6 @@ CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
-CONFIG_PROBE_INITRD_HEADER=y
 # CONFIG_FREEZER is not set
 
 #
@@ -1053,7 +1051,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 94b7d57..267bd46 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 CONFIG_BCM47XX=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1853,7 +1852,7 @@ CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index ea00c18..7fee027 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 CONFIG_BCM63XX=y
 # CONFIG_MIPS_COBALT is not set
@@ -942,7 +941,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 13d9eb4..c2f06e3 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1237,7 +1236,7 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_SB1XXX_CORELIS is not set
 # CONFIG_RUNTIME_DEBUG is not set
index 185df23..72b7e45 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -783,7 +782,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 7afaa28..c8507bc 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -269,7 +268,6 @@ CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 CONFIG_CLASSIC_RCU=y
-# CONFIG_PROBE_INITRD_HEADER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -822,7 +820,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
index 6c8cca8..49e6131 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
@@ -1126,7 +1125,7 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index dbdf3bb..68e90cd 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_DB1000=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1090,7 +1089,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index fa68144..9081283 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_DB1100=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1090,7 +1089,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index d73f1de..dabf030 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_DB1550 is not set
 CONFIG_MIPS_DB1200=y
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1172,7 +1171,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=48M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index ec3e028..a151313 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_DB1500=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1390,7 +1389,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 7631dae..6b64339 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MACH_ALCHEMY=y
 CONFIG_MIPS_DB1550=y
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1207,7 +1206,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 9e65e6a..cbb4d86 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MACH_JAZZ is not set
@@ -882,7 +881,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 1bd84d4..52968c4 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -561,7 +560,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
deleted file mode 100644 (file)
index 1995d43..0000000
+++ /dev/null
@@ -1,1335 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:31 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-CONFIG_BASLER_EXCITE=y
-# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_COHERENT=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_CPU_RM9K=y
-CONFIG_MIPS_RM9122=y
-CONFIG_SERIAL_RM9000=y
-CONFIG_GPI_RM9000=y
-CONFIG_WDT_RM9000=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-# CONFIG_PREEMPT_NONE is not set
-# CONFIG_PREEMPT_VOLUNTARY is not set
-CONFIG_PREEMPT=y
-CONFIG_PREEMPT_BKL=y
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND_IDS=y
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_BASLER_EXCITE is not set
-# CONFIG_MTD_NAND_CAFE is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
-# CONFIG_SCSI_NETLINK is not set
-# CONFIG_SCSI_PROC_FS is not set
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_WDT_RM9K_GPI=m
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=m
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_SPLIT_ISO is not set
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=m
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=m
-CONFIG_CRYPTO_MANAGER=m
-# CONFIG_CRYPTO_HMAC is not set
-CONFIG_CRYPTO_XCBC=m
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-# CONFIG_CRYPTO_DES is not set
-CONFIG_CRYPTO_FCRYPT=m
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
index 0197f0d..a09dd03 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31-rc1
-# Thu Jul  2 22:37:00 2009
+# Linux kernel version: 2.6.32-rc4
+# Fri Oct 16 13:18:01 2009
 #
 CONFIG_MIPS=y
 
@@ -10,8 +10,8 @@ CONFIG_MIPS=y
 #
 # CONFIG_MACH_ALCHEMY is not set
 # CONFIG_AR7 is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -105,6 +105,8 @@ CONFIG_CPU_LOONGSON2E=y
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
 # CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
 CONFIG_CPU_LOONGSON2=y
 CONFIG_SYS_HAS_CPU_LOONGSON2E=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
@@ -135,12 +137,16 @@ CONFIG_SYS_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
 CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_PHYS_ADDR_T_64BIT=y
@@ -148,6 +154,7 @@ CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
@@ -180,6 +187,12 @@ CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION="-fuloong2e"
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -193,11 +206,12 @@ CONFIG_BSD_PROCESS_ACCT=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=64
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -235,18 +249,16 @@ CONFIG_SHMEM=y
 CONFIG_AIO=y
 
 #
-# Performance Counters
+# Kernel Performance Events And Counters
 #
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_SYSCALL_WRAPPERS=y
@@ -255,8 +267,8 @@ CONFIG_HAVE_SYSCALL_WRAPPERS=y
 # GCOV-based kernel profiling
 #
 # CONFIG_GCOV_KERNEL is not set
-# CONFIG_SLOW_WORK is not set
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -283,7 +295,7 @@ CONFIG_IOSCHED_CFQ=y
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_FREEZER is not set
+CONFIG_FREEZER=y
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -321,9 +333,14 @@ CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
 # CONFIG_SUSPEND is not set
-# CONFIG_HIBERNATION is not set
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/hda3"
+# CONFIG_PM_RUNTIME is not set
 CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
 
 #
 # Networking options
@@ -442,6 +459,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -473,6 +491,7 @@ CONFIG_NET_CLS_ROUTE=y
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
 CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
@@ -481,7 +500,6 @@ CONFIG_WIRELESS_EXT_SYSFS=y
 #
 # CFG80211 needs to be enabled for MAC80211
 #
-CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 CONFIG_NET_9P=m
@@ -495,6 +513,7 @@ CONFIG_NET_9P=m
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
@@ -504,9 +523,9 @@ CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=m
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_TESTS is not set
 
 #
 # User Modules And Translation Layers
@@ -820,6 +839,7 @@ CONFIG_8139TOO=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -867,10 +887,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
 # CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -886,6 +903,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_USB_CDC_PHONET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -933,12 +951,16 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -946,6 +968,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
 CONFIG_MOUSE_PS2_SYNAPTICS=y
 CONFIG_MOUSE_PS2_TRACKPOINT=y
 # CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_APPLETOUCH is not set
@@ -1015,6 +1038,7 @@ CONFIG_RTC=y
 CONFIG_DEVPORT=y
 CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=m
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -1070,9 +1094,6 @@ CONFIG_I2C_VIAPRO=m
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -1088,7 +1109,6 @@ CONFIG_I2C_VIAPRO=m
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -1105,6 +1125,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_AB3100_CORE is not set
@@ -1114,6 +1135,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # Graphics support
 #
+CONFIG_VGA_ARB=y
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
@@ -1198,6 +1220,7 @@ CONFIG_FONT_8x16=y
 # CONFIG_LOGO is not set
 CONFIG_SOUND=y
 CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -1304,7 +1327,6 @@ CONFIG_SND_USB=y
 CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
 CONFIG_HIDRAW=y
 
 #
@@ -1356,6 +1378,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_ISP1760_HCD=m
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1453,6 +1476,7 @@ CONFIG_UIO_CIF=m
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_AEC is not set
 # CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
 
 #
 # TI VLYNQ
@@ -1469,10 +1493,10 @@ CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=m
-CONFIG_EXT4DEV_COMPAT=y
 CONFIG_EXT4_FS_XATTR=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
 CONFIG_FS_XIP=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
@@ -1489,6 +1513,7 @@ CONFIG_FS_POSIX_ACL=y
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_FILE_LOCKING=y
 CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
@@ -1557,7 +1582,6 @@ CONFIG_OMFS_FS=m
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -1666,6 +1690,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=2048
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
@@ -1678,13 +1703,14 @@ CONFIG_NOP_TRACER=y
 CONFIG_RING_BUFFER=y
 CONFIG_EVENT_TRACING=y
 CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
 # CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
@@ -1742,11 +1768,13 @@ CONFIG_CRYPTO_XTS=m
 #
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_GHASH=m
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
index f14d38b..222d7ec 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1188,7 +1187,7 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DYNAMIC_PRINTK_DEBUG=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 1fc73aa..ed84b4c 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -940,7 +939,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 539dccb..dab2e5a 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -816,7 +815,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index d934bde..1841c88 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1126,7 +1125,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index d22df61..14c2ab3 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MACH_JAZZ=y
@@ -1374,7 +1373,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 5380f1f..4d66c44 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -835,7 +834,7 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 044074d..08d481e 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -798,7 +797,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
new file mode 100644 (file)
index 0000000..b71a0a4
--- /dev/null
@@ -0,0 +1,1835 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc6
+# Mon Nov  9 23:42:42 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+CONFIG_MACH_LOONGSON=y
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+# CONFIG_LEMOTE_FULOONG2E is not set
+CONFIG_LEMOTE_MACH2F=y
+CONFIG_CS5536=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2E is not set
+CONFIG_CPU_LOONGSON2F=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
+CONFIG_CPU_LOONGSON2=y
+CONFIG_SYS_HAS_CPU_LOONGSON2F=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=64
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_SYSCALL_WRAPPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/hda3"
+# CONFIG_PM_RUNTIME is not set
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+CONFIG_DEFAULT_BIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="bic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# 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
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+# CONFIG_NET_EMATCH_CMP is not set
+# CONFIG_NET_EMATCH_NBYTE is not set
+# CONFIG_NET_EMATCH_U32 is not set
+# CONFIG_NET_EMATCH_META is not set
+# CONFIG_NET_EMATCH_TEXT is not set
+CONFIG_NET_CLS_ACT=y
+# CONFIG_NET_ACT_POLICE is not set
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=m
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_PNP is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 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
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+
+#
+# Other IDE chipsets support
+#
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+# CONFIG_BLK_DEV_4DRIVES is not set
+# CONFIG_BLK_DEV_ALI14XX is not set
+# CONFIG_BLK_DEV_DTC2278 is not set
+# CONFIG_BLK_DEV_HT6560B is not set
+# CONFIG_BLK_DEV_QD65XX is not set
+# CONFIG_BLK_DEV_UMC8672 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_PRE80211=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2_ALPS is not set
+# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+# CONFIG_MOUSE_PS2_TRACKPOINT is not set
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_STALDRV is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_FOURPORT=y
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_STRADIS is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+CONFIG_FB_SIS=y
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_7x14=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+CONFIG_FONT_10x18=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+CONFIG_SND_CS5535AUDIO=m
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_MIPS is not set
+# CONFIG_SND_USB is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# 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
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_ALTERA_PCIE_CHDMA is not set
+# CONFIG_RTL8187SE is not set
+# CONFIG_RTL8192SU is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+
+#
+# Qualcomm MSM Camera And Video
+#
+
+#
+# Camera Sensor Selection
+#
+# CONFIG_INPUT_GPIO is not set
+# CONFIG_DST is not set
+# CONFIG_POHMELFS is not set
+# CONFIG_B3DFG is not set
+# CONFIG_PLAN9AUTH is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_VME_BUS is not set
+
+#
+# RAR Register Driver
+#
+# CONFIG_RAR_REGISTER is not set
+# CONFIG_IIO is not set
+CONFIG_FB_SM7XX=y
+CONFIG_FB_SM7XX_ACCEL=y
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index 3f01870..d3c6012 100644 (file)
@@ -10,7 +10,6 @@ CONFIG_MIPS=y
 #
 CONFIG_ZONE_DMA=y
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1591,7 +1590,7 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index d001f7e..6a325c0 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1366,7 +1365,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 7358454..f77a34e 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -635,7 +634,9 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
index 8c720e5..1720305 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -817,7 +816,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index ecbc030..000d185 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1412,7 +1411,7 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
index 9477f04..144b94d 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 CONFIG_MACH_ALCHEMY=y
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -3018,7 +3017,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index be8091e..ddf67f6 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_PB1100=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1083,7 +1082,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index e74ba79..5ec6083 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_PB1500=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1200,7 +1199,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 1d896fd..6647642 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MIPS_PB1550=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1193,7 +1192,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index fef4d31..848344d 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1034,7 +1033,7 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
 # CONFIG_KERNEL_TESTS is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index e10c711..9d721fd 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1215,7 +1214,9 @@ CONFIG_DEBUG_MUTEXES=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
index 5ed3c8d..ab07ec0 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1205,7 +1204,9 @@ CONFIG_DEBUG_SLAB=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig
new file mode 100644 (file)
index 0000000..7291633
--- /dev/null
@@ -0,0 +1,1550 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc5
+# Fri Aug 28 14:49:33 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+CONFIG_POWERTV=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+# CONFIG_MIN_RUNTIME_RESOURCES is not set
+# CONFIG_BOOTLOADER_DRIVER is not set
+CONFIG_BOOTLOADER_FAMILY="R2"
+CONFIG_CSRC_POWERTV=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+CONFIG_TIMERFD=y
+# CONFIG_EVENTFD is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_PROBE_INITRD_HEADER is not set
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=y
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+# CONFIG_IP_NF_ARP_MANGLE is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_FILTER=y
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+CONFIG_NET_SCH_TBF=y
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP210X=y
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# 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
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10.0.1.1:255.255.255.0:zeus:eth0: root=/dev/nfs nfsroot=/nfsroot/cramfs,wsize=512,rsize=512,tcp nokgdb console=ttyUSB0,115200 memsize=252M"
+# CONFIG_CMDLINE_OVERRIDE is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_RUNTIME_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index f40c3a0..57a5048 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1204,7 +1203,7 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 6c6a19a..21c2022 100644 (file)
@@ -10,7 +10,6 @@ CONFIG_MIPS=y
 #
 # CONFIG_MACH_ALCHEMY is not set
 # CONFIG_AR7 is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_BCM63XX is not set
 # CONFIG_MIPS_COBALT is not set
@@ -284,7 +283,6 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_PROBE_INITRD_HEADER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -1063,7 +1061,7 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index e53b8d0..7903628 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1694,7 +1693,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
index 7f38c0b..7f07bf0 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -961,7 +960,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_SB1XXX_CORELIS is not set
 
 #
index b505988..c54d112 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -892,7 +891,9 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index b06a716..e7c5cd3 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -895,7 +894,9 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=32M console=ttyVR0,115200"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 46512cf..b50032b 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1077,7 +1076,9 @@ CONFIG_FRAME_WARN=1024
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index b437eb7..c02ba08 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MIPS=y
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -755,7 +754,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 06acc74..a35bc41 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -887,7 +886,9 @@ CONFIG_ENABLE_MUST_CHECK=y
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200n8"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
index 69feaf8..e3d68d6 100644 (file)
@@ -22,7 +22,6 @@ CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -824,7 +823,7 @@ CONFIG_DEBUG_MUTEXES=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
index 4ca4eef..5c8603c 100644 (file)
 
 #undef DEBUG_CMDLINE
 
-char * __init prom_getcmdline(void)
-{
-       return arcs_cmdline;
-}
-
 static char *ignored[] = {
        "ConsoleIn=",
        "ConsoleOut=",
diff --git a/arch/mips/include/asm/asm-offsets.h b/arch/mips/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index f5dfaf6..09eee09 100644 (file)
@@ -67,9 +67,9 @@
 #define MACH_LEMOTE_ML2F7      3
 #define MACH_LEMOTE_YL2F89     4
 #define MACH_DEXXON_GDIUM2F10  5
-#define MACH_LOONGSON_END      6
-
-#define CL_SIZE                        COMMAND_LINE_SIZE
+#define MACH_LEMOTE_NAS        6
+#define MACH_LEMOTE_LL2F       7
+#define MACH_LOONGSON_END      8
 
 extern char *system_type;
 const char *get_system_type(void);
@@ -107,7 +107,7 @@ extern void free_init_pages(const char *what,
 /*
  * Initial kernel command line, usually setup by prom_init()
  */
-extern char arcs_cmdline[CL_SIZE];
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
 
 /*
  * Registers a0, a1, a3 and a4 as passed to the kernel entry by firmware
diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h
new file mode 100644 (file)
index 0000000..83894aa
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __ASM_MIPS_CLOCK_H
+#define __ASM_MIPS_CLOCK_H
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/clk.h>
+
+extern void (*cpu_wait) (void);
+
+struct clk;
+
+struct clk_ops {
+       void (*init) (struct clk *clk);
+       void (*enable) (struct clk *clk);
+       void (*disable) (struct clk *clk);
+       void (*recalc) (struct clk *clk);
+       int (*set_rate) (struct clk *clk, unsigned long rate, int algo_id);
+       long (*round_rate) (struct clk *clk, unsigned long rate);
+};
+
+struct clk {
+       struct list_head node;
+       const char *name;
+       int id;
+       struct module *owner;
+
+       struct clk *parent;
+       struct clk_ops *ops;
+
+       struct kref kref;
+
+       unsigned long rate;
+       unsigned long flags;
+};
+
+#define CLK_ALWAYS_ENABLED     (1 << 0)
+#define CLK_RATE_PROPAGATES    (1 << 1)
+
+/* Should be defined by processor-specific code */
+void arch_init_clk_ops(struct clk_ops **, int type);
+
+int clk_init(void);
+
+int __clk_enable(struct clk *);
+void __clk_disable(struct clk *);
+
+void clk_recalc_rate(struct clk *);
+
+int clk_register(struct clk *);
+void clk_unregister(struct clk *);
+
+/* the exported API, in addition to clk_set_rate */
+/**
+ * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ * @algo_id: algorithm id to be passed down to ops->set_rate
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id);
+
+#endif                         /* __ASM_MIPS_CLOCK_H */
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
new file mode 100644 (file)
index 0000000..6b04c98
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_COP2_H
+#define __ASM_COP2_H
+
+enum cu2_ops {
+       CU2_EXCEPTION,
+       CU2_LWC2_OP,
+       CU2_LDC2_OP,
+       CU2_SWC2_OP,
+       CU2_SDC2_OP,
+};
+
+extern int register_cu2_notifier(struct notifier_block *nb);
+extern int cu2_notifier_call_chain(unsigned long val, void *v);
+
+#endif /* __ASM_COP2_H */
index 4b96d1a..cf373a9 100644 (file)
 #define PRID_REV_VR4181A       0x0070  /* Same as VR4122 */
 #define PRID_REV_VR4130                0x0080
 #define PRID_REV_34K_V1_0_2    0x0022
+#define PRID_REV_LOONGSON2E    0x0002
+#define PRID_REV_LOONGSON2F    0x0003
 
 /*
  * Older processors used to encode processor version and revision in two
index 7c6681a..e482fe9 100644 (file)
@@ -19,7 +19,7 @@
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
 #define O_LARGEFILE    0x2000  /* allow large file opens */
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
index 8a3ef24..7fcef8e 100644 (file)
 struct sigcontext;
 struct sigcontext32;
 
-extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
-extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
-extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
 extern void fpu_emulator_init_fpu(void);
-extern int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern int fpu_emulator_restore_context(struct sigcontext __user *sc);
 extern void _init_fpu(void);
 extern void _save_fp(struct task_struct *);
 extern void _restore_fp(struct task_struct *);
index e518957..aecada6 100644 (file)
 
 #include <asm/break.h>
 #include <asm/inst.h>
+#include <asm/local.h>
+
+#ifdef CONFIG_DEBUG_FS
 
 struct mips_fpu_emulator_stats {
-       unsigned int emulated;
-       unsigned int loads;
-       unsigned int stores;
-       unsigned int cp1ops;
-       unsigned int cp1xops;
-       unsigned int errors;
+       local_t emulated;
+       local_t loads;
+       local_t stores;
+       local_t cp1ops;
+       local_t cp1xops;
+       local_t errors;
 };
 
-extern struct mips_fpu_emulator_stats fpuemustats;
+DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+
+#define MIPS_FPU_EMU_INC_STATS(M)                                      \
+       cpu_local_wrap(__local_inc(&__get_cpu_var(fpuemustats).M))
+
+#else
+#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)
+#endif /* CONFIG_DEBUG_FS */
 
 extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
        unsigned long cpc);
index 40a8c17..3986cd8 100644 (file)
@@ -1 +1,90 @@
-/* empty */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef _ASM_MIPS_FTRACE_H
+#define _ASM_MIPS_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+#define MCOUNT_INSN_SIZE 4             /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(void);
+#define mcount _mcount
+
+#define safe_load(load, src, dst, error)               \
+do {                                                   \
+       asm volatile (                                  \
+               "1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
+               "   li %[" STR(error) "], 0\n"          \
+               "2:\n"                                  \
+                                                       \
+               ".section .fixup, \"ax\"\n"             \
+               "3: li %[" STR(error) "], 1\n"          \
+               "   j 2b\n"                             \
+               ".previous\n"                           \
+                                                       \
+               ".section\t__ex_table,\"a\"\n\t"        \
+               STR(PTR) "\t1b, 3b\n\t"                 \
+               ".previous\n"                           \
+                                                       \
+               : [dst] "=&r" (dst), [error] "=r" (error)\
+               : [src] "r" (src)                       \
+               : "memory"                              \
+       );                                              \
+} while (0)
+
+#define safe_store(store, src, dst, error)     \
+do {                                           \
+       asm volatile (                          \
+               "1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
+               "   li %[" STR(error) "], 0\n"  \
+               "2:\n"                          \
+                                               \
+               ".section .fixup, \"ax\"\n"     \
+               "3: li %[" STR(error) "], 1\n"  \
+               "   j 2b\n"                     \
+               ".previous\n"                   \
+                                               \
+               ".section\t__ex_table,\"a\"\n\t"\
+               STR(PTR) "\t1b, 3b\n\t"         \
+               ".previous\n"                   \
+                                               \
+               : [error] "=r" (error)          \
+               : [dst] "r" (dst), [src] "r" (src)\
+               : "memory"                      \
+       );                                      \
+} while (0)
+
+#define safe_load_code(dst, src, error) \
+       safe_load(STR(lw), src, dst, error)
+#define safe_store_code(src, dst, error) \
+       safe_store(STR(sw), src, dst, error)
+
+#define safe_load_stack(dst, src, error) \
+       safe_load(STR(PTR_L), src, dst, error)
+
+#define safe_store_stack(src, dst, error) \
+       safe_store(STR(PTR_S), src, dst, error)
+
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+       return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+
+#endif /*  CONFIG_DYNAMIC_FTRACE */
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+#endif /* _ASM_MIPS_FTRACE_H */
index 09b08d0..0696036 100644 (file)
@@ -113,36 +113,11 @@ do {                                                                      \
 
 #endif
 
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- *
- * Ideally there should be away to get this into kernel/irq/handle.c to
- * avoid the overhead of a call for just a tiny function ...
- */
-#define do_IRQ(irq)                                                    \
-do {                                                                   \
-       irq_enter();                                                    \
-       __DO_IRQ_SMTC_HOOK(irq);                                        \
-       generic_handle_irq(irq);                                        \
-       irq_exit();                                                     \
-} while (0)
+extern void do_IRQ(unsigned int irq);
 
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * To avoid inefficient and in some cases pathological re-checking of
- * IRQ affinity, we have this variant that skips the affinity check.
- */
-
 
-#define do_IRQ_no_affinity(irq)                                                \
-do {                                                                   \
-       irq_enter();                                                    \
-       __NO_AFFINITY_IRQ_SMTC_HOOK(irq);                               \
-       generic_handle_irq(irq);                                        \
-       irq_exit();                                                     \
-} while (0)
+extern void do_IRQ_no_affinity(unsigned int irq);
 
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 
diff --git a/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h
deleted file mode 100644 (file)
index 107104c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Thomas Koeller <thomas.koeller@baslerweb.com>
- * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
- */
-#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Basler eXcite has an RM9122 processor.
- */
-#define cpu_has_watch          1
-#define cpu_has_mips16         0
-#define cpu_has_divec          0
-#define cpu_has_vce            0
-#define cpu_has_cache_cdex_p   0
-#define cpu_has_cache_cdex_s   0
-#define cpu_has_prefetch       1
-#define cpu_has_mcheck         0
-#define cpu_has_ejtag          0
-
-#define cpu_has_llsc           1
-#define cpu_has_vtag_icache    0
-#define cpu_has_dc_aliases     0
-#define cpu_has_ic_fills_f_dc  0
-#define cpu_has_dsp            0
-#define cpu_icache_snoops_remote_store 0
-#define cpu_has_mipsmt         0
-#define cpu_has_userlocal      0
-
-#define cpu_has_nofpuex                0
-#define cpu_has_64bits         1
-
-#define cpu_has_mips32r1       0
-#define cpu_has_mips32r2       0
-#define cpu_has_mips64r1       0
-#define cpu_has_mips64r2       0
-
-#define cpu_has_inclusive_pcaches      0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-excite/excite.h b/arch/mips/include/asm/mach-excite/excite.h
deleted file mode 100644 (file)
index 4c29ba4..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-#ifndef __EXCITE_H__
-#define __EXCITE_H__
-
-#include <linux/init.h>
-#include <asm/addrspace.h>
-#include <asm/types.h>
-
-#define EXCITE_CPU_EXT_CLOCK 100000000
-
-#if !defined(__ASSEMBLY__)
-void __init excite_kgdb_init(void);
-void excite_procfs_init(void);
-extern unsigned long memsize;
-extern char modetty[];
-extern u32 unit_id;
-#endif
-
-/* Base name for XICAP devices */
-#define XICAP_NAME     "xicap_gpi"
-
-/* OCD register offsets */
-#define LKB0           0x0038
-#define LKB5           0x0128
-#define LKM5           0x012C
-#define LKB7           0x0138
-#define LKM7           0x013c
-#define LKB8           0x0140
-#define LKM8           0x0144
-#define LKB9           0x0148
-#define LKM9           0x014c
-#define LKB10          0x0150
-#define LKM10          0x0154
-#define LKB11          0x0158
-#define LKM11          0x015c
-#define LKB12          0x0160
-#define LKM12          0x0164
-#define LKB13          0x0168
-#define LKM13          0x016c
-#define LDP0           0x0200
-#define LDP1           0x0210
-#define LDP2           0x0220
-#define LDP3           0x0230
-#define INTPIN0                0x0A40
-#define INTPIN1                0x0A44
-#define INTPIN2                0x0A48
-#define INTPIN3                0x0A4C
-#define INTPIN4                0x0A50
-#define INTPIN5                0x0A54
-#define INTPIN6                0x0A58
-#define INTPIN7                0x0A5C
-
-
-
-
-/* TITAN register offsets */
-#define CPRR           0x0004
-#define CPDSR          0x0008
-#define CPTC0R         0x000c
-#define CPTC1R         0x0010
-#define CPCFG0         0x0020
-#define CPCFG1         0x0024
-#define CPDST0A                0x0028
-#define CPDST0B                0x002c
-#define CPDST1A                0x0030
-#define CPDST1B                0x0034
-#define CPXDSTA                0x0038
-#define CPXDSTB                0x003c
-#define CPXCISRA       0x0048
-#define CPXCISRB       0x004c
-#define CPGIG0ER       0x0050
-#define CPGIG1ER       0x0054
-#define CPGRWL         0x0068
-#define CPURSLMT       0x00f8
-#define UACFG          0x0200
-#define UAINTS         0x0204
-#define SDRXFCIE       0x4828
-#define SDTXFCIE       0x4928
-#define INTP0Status0   0x1B00
-#define INTP0Mask0     0x1B04
-#define INTP0Set0      0x1B08
-#define INTP0Clear0    0x1B0C
-#define GXCFG          0x5000
-#define GXDMADRPFX     0x5018
-#define GXDMA_DESCADR  0x501c
-#define GXCH0TDESSTRT  0x5054
-
-/* IRQ definitions */
-#define NMICONFIG              0xac0
-#define TITAN_MSGINT   0xc4
-#define TITAN_IRQ      ((TITAN_MSGINT / 0x20) + 2)
-#define FPGA0_MSGINT   0x5a
-#define FPGA0_IRQ      ((FPGA0_MSGINT / 0x20) + 2)
-#define FPGA1_MSGINT   0x7b
-#define FPGA1_IRQ      ((FPGA1_MSGINT / 0x20) + 2)
-#define PHY_MSGINT     0x9c
-#define PHY_IRQ                ((PHY_MSGINT   / 0x20) + 2)
-
-#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE)
-/* Pre-release units used interrupt pin #9 */
-#define USB_IRQ                11
-#else
-/* Re-designed units use interrupt pin #1 */
-#define USB_MSGINT     0x39
-#define USB_IRQ                ((USB_MSGINT / 0x20) + 2)
-#endif
-#define TIMER_IRQ      12
-
-
-/* Device address ranges */
-#define EXCITE_OFFS_OCD                0x1fffc000
-#define        EXCITE_SIZE_OCD         (16 * 1024)
-#define EXCITE_PHYS_OCD                CPHYSADDR(EXCITE_OFFS_OCD)
-#define EXCITE_ADDR_OCD                CKSEG1ADDR(EXCITE_OFFS_OCD)
-
-#define EXCITE_OFFS_SCRAM      0x1fffa000
-#define        EXCITE_SIZE_SCRAM       (8 << 10)
-#define EXCITE_PHYS_SCRAM      CPHYSADDR(EXCITE_OFFS_SCRAM)
-#define EXCITE_ADDR_SCRAM      CKSEG1ADDR(EXCITE_OFFS_SCRAM)
-
-#define EXCITE_OFFS_PCI_IO     0x1fff8000
-#define        EXCITE_SIZE_PCI_IO      (8 << 10)
-#define EXCITE_PHYS_PCI_IO     CPHYSADDR(EXCITE_OFFS_PCI_IO)
-#define EXCITE_ADDR_PCI_IO     CKSEG1ADDR(EXCITE_OFFS_PCI_IO)
-
-#define EXCITE_OFFS_TITAN      0x1fff0000
-#define EXCITE_SIZE_TITAN      (32 << 10)
-#define EXCITE_PHYS_TITAN      CPHYSADDR(EXCITE_OFFS_TITAN)
-#define EXCITE_ADDR_TITAN      CKSEG1ADDR(EXCITE_OFFS_TITAN)
-
-#define EXCITE_OFFS_PCI_MEM    0x1ffe0000
-#define EXCITE_SIZE_PCI_MEM    (64 << 10)
-#define EXCITE_PHYS_PCI_MEM    CPHYSADDR(EXCITE_OFFS_PCI_MEM)
-#define EXCITE_ADDR_PCI_MEM    CKSEG1ADDR(EXCITE_OFFS_PCI_MEM)
-
-#define EXCITE_OFFS_FPGA       0x1ffdc000
-#define EXCITE_SIZE_FPGA       (16 << 10)
-#define EXCITE_PHYS_FPGA       CPHYSADDR(EXCITE_OFFS_FPGA)
-#define EXCITE_ADDR_FPGA       CKSEG1ADDR(EXCITE_OFFS_FPGA)
-
-#define EXCITE_OFFS_NAND       0x1ffd8000
-#define EXCITE_SIZE_NAND       (16 << 10)
-#define EXCITE_PHYS_NAND       CPHYSADDR(EXCITE_OFFS_NAND)
-#define EXCITE_ADDR_NAND       CKSEG1ADDR(EXCITE_OFFS_NAND)
-
-#define EXCITE_OFFS_BOOTROM    0x1f000000
-#define EXCITE_SIZE_BOOTROM    (8 << 20)
-#define EXCITE_PHYS_BOOTROM    CPHYSADDR(EXCITE_OFFS_BOOTROM)
-#define EXCITE_ADDR_BOOTROM    CKSEG1ADDR(EXCITE_OFFS_BOOTROM)
-
-/* FPGA address offsets */
-#define EXCITE_FPGA_DPR                0x0104  /* dual-ported ram */
-#define EXCITE_FPGA_SYSCTL     0x0200  /* system control register block */
-
-#endif /* __EXCITE_H__ */
diff --git a/arch/mips/include/asm/mach-excite/excite_fpga.h b/arch/mips/include/asm/mach-excite/excite_fpga.h
deleted file mode 100644 (file)
index 0a1ef69..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef EXCITE_FPGA_H_INCLUDED
-#define EXCITE_FPGA_H_INCLUDED
-
-
-/**
- * Address alignment of the individual FPGA bytes.
- * The address arrangement of the individual bytes of the FPGA is two
- * byte aligned at the embedded MK2 platform.
- */
-#ifdef EXCITE_CCI_FPGA_MK2
-typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
-#else
-typedef unsigned char excite_cci_fpga_align_t;
-#endif
-
-
-/**
- * Size of Dual Ported RAM.
- */
-#define EXCITE_DPR_SIZE 263
-
-
-/**
- * Size of Reserved Status Fields in Dual Ported RAM.
- */
-#define EXCITE_DPR_STATUS_SIZE 7
-
-
-
-/**
- * FPGA.
- * Hardware register layout of the FPGA interface. The FPGA must accessed
- * byte wise solely.
- * @see EXCITE_CCI_DPR_MK2
- */
-typedef struct excite_fpga {
-
-       /**
-        * Dual Ported RAM.
-        */
-       excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
-
-       /**
-        * Status.
-        */
-       excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
-
-#ifdef EXCITE_CCI_FPGA_MK2
-       /**
-        * RM9000 Interrupt.
-        * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
-        */
-       excite_cci_fpga_align_t rm9k_int;
-#else
-       /**
-        * MK2 Interrupt.
-        * Write access initiates interrupt at the ARM processor of the MK2.
-        */
-       excite_cci_fpga_align_t mk2_int;
-
-       excite_cci_fpga_align_t gap[0x1000-0x10f];
-
-       /**
-        * IRQ Source/Acknowledge.
-        */
-       excite_cci_fpga_align_t rm9k_irq_src;
-
-       /**
-        * IRQ Mask.
-        * Set bits enable the related interrupt.
-        */
-       excite_cci_fpga_align_t rm9k_irq_mask;
-#endif
-
-
-} excite_fpga;
-
-
-
-#endif /* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/include/asm/mach-excite/excite_nandflash.h b/arch/mips/include/asm/mach-excite/excite_nandflash.h
deleted file mode 100644 (file)
index c4cf614..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __EXCITE_NANDFLASH_H__
-#define __EXCITE_NANDFLASH_H__
-
-/* Resource names */
-#define EXCITE_NANDFLASH_RESOURCE_REGS "excite_nandflash_regs"
-
-#endif /* __EXCITE_NANDFLASH_H__ */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_eth.h b/arch/mips/include/asm/mach-excite/rm9k_eth.h
deleted file mode 100644 (file)
index 94705a4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#if !defined(__RM9K_ETH_H__)
-#define __RM9K_ETH_H__
-
-#define RM9K_GE_NAME                   "rm9k_ge"
-
-/* Resource names */
-#define RM9K_GE_RESOURCE_MAC           "rm9k_ge_mac"
-#define RM9K_GE_RESOURCE_MSTAT         "rm9k_ge_mstat"
-#define RM9K_GE_RESOURCE_PKTPROC       "rm9k_ge_pktproc"
-#define RM9K_GE_RESOURCE_XDMA          "rm9k_ge_xdma"
-#define RM9K_GE_RESOURCE_FIFO_RX       "rm9k_ge_fifo_rx"
-#define RM9K_GE_RESOURCE_FIFO_TX       "rm9k_ge_fifo_tx"
-#define RM9K_GE_RESOURCE_FIFOMEM_RX    "rm9k_ge_fifo_memory_rx"
-#define RM9K_GE_RESOURCE_FIFOMEM_TX    "rm9k_ge_fifo_memory_tx"
-#define RM9K_GE_RESOURCE_PHY           "rm9k_ge_phy"
-#define RM9K_GE_RESOURCE_DMADESC_RX    "rm9k_ge_dmadesc_rx"
-#define RM9K_GE_RESOURCE_DMADESC_TX    "rm9k_ge_dmadesc_tx"
-#define RM9K_GE_RESOURCE_IRQ_MAIN      "rm9k_ge_irq_main"
-#define RM9K_GE_RESOURCE_IRQ_PHY       "rm9k_ge_irq_phy"
-#define RM9K_GE_RESOURCE_GPI_SLICE     "rm9k_ge_gpi_slice"
-#define RM9K_GE_RESOURCE_MDIO_CHANNEL  "rm9k_ge_mdio_channel"
-
-#endif /* !defined(__RM9K_ETH_H__) */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_wdt.h b/arch/mips/include/asm/mach-excite/rm9k_wdt.h
deleted file mode 100644 (file)
index 3fa3c08..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __RM9K_WDT_H__
-#define __RM9K_WDT_H__
-
-/* Device name */
-#define WDT_NAME               "wdt_gpi"
-
-/* Resource names */
-#define WDT_RESOURCE_REGS      "excite_watchdog_regs"
-#define WDT_RESOURCE_IRQ       "excite_watchdog_irq"
-#define WDT_RESOURCE_COUNTER   "excite_watchdog_counter"
-
-#endif /* __RM9K_WDT_H__ */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_xicap.h b/arch/mips/include/asm/mach-excite/rm9k_xicap.h
deleted file mode 100644 (file)
index 0095777..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __EXCITE_XICAP_H__
-#define __EXCITE_XICAP_H__
-
-
-/* Resource names */
-#define XICAP_RESOURCE_FIFO_RX         "xicap_fifo_rx"
-#define XICAP_RESOURCE_FIFO_TX         "xicap_fifo_tx"
-#define XICAP_RESOURCE_XDMA            "xicap_xdma"
-#define XICAP_RESOURCE_DMADESC         "xicap_dmadesc"
-#define XICAP_RESOURCE_PKTPROC         "xicap_pktproc"
-#define XICAP_RESOURCE_IRQ             "xicap_irq"
-#define XICAP_RESOURCE_GPI_SLICE       "xicap_gpi_slice"
-#define XICAP_RESOURCE_FIFO_BLK                "xicap_fifo_blocks"
-#define XICAP_RESOURCE_PKT_STREAM      "xicap_pkt_stream"
-
-#endif /* __EXCITE_XICAP_H__ */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
new file mode 100644 (file)
index 0000000..021f77c
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * The header file of cs5536 sourth bridge.
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu <liujl@lemote.com>
+ */
+
+#ifndef        _CS5536_H
+#define        _CS5536_H
+
+#include <linux/types.h>
+
+extern void _rdmsr(u32 msr, u32 *hi, u32 *lo);
+extern void _wrmsr(u32 msr, u32 hi, u32 lo);
+
+/*
+ * MSR module base
+ */
+#define        CS5536_SB_MSR_BASE      (0x00000000)
+#define        CS5536_GLIU_MSR_BASE    (0x10000000)
+#define        CS5536_ILLEGAL_MSR_BASE (0x20000000)
+#define        CS5536_USB_MSR_BASE     (0x40000000)
+#define        CS5536_IDE_MSR_BASE     (0x60000000)
+#define        CS5536_DIVIL_MSR_BASE   (0x80000000)
+#define        CS5536_ACC_MSR_BASE     (0xa0000000)
+#define        CS5536_UNUSED_MSR_BASE  (0xc0000000)
+#define        CS5536_GLCP_MSR_BASE    (0xe0000000)
+
+#define        SB_MSR_REG(offset)      (CS5536_SB_MSR_BASE     | (offset))
+#define        GLIU_MSR_REG(offset)    (CS5536_GLIU_MSR_BASE   | (offset))
+#define        ILLEGAL_MSR_REG(offset) (CS5536_ILLEGAL_MSR_BASE | (offset))
+#define        USB_MSR_REG(offset)     (CS5536_USB_MSR_BASE    | (offset))
+#define        IDE_MSR_REG(offset)     (CS5536_IDE_MSR_BASE    | (offset))
+#define        DIVIL_MSR_REG(offset)   (CS5536_DIVIL_MSR_BASE  | (offset))
+#define        ACC_MSR_REG(offset)     (CS5536_ACC_MSR_BASE    | (offset))
+#define        UNUSED_MSR_REG(offset)  (CS5536_UNUSED_MSR_BASE | (offset))
+#define        GLCP_MSR_REG(offset)    (CS5536_GLCP_MSR_BASE   | (offset))
+
+/*
+ * BAR SPACE OF VIRTUAL PCI :
+ * range for pci probe use, length is the actual size.
+ */
+/* IO space for all DIVIL modules */
+#define        CS5536_IRQ_RANGE        0xffffffe0 /* USERD FOR PCI PROBE */
+#define        CS5536_IRQ_LENGTH       0x20    /* THE REGS ACTUAL LENGTH */
+#define        CS5536_SMB_RANGE        0xfffffff8
+#define        CS5536_SMB_LENGTH       0x08
+#define        CS5536_GPIO_RANGE       0xffffff00
+#define        CS5536_GPIO_LENGTH      0x100
+#define        CS5536_MFGPT_RANGE      0xffffffc0
+#define        CS5536_MFGPT_LENGTH     0x40
+#define        CS5536_ACPI_RANGE       0xffffffe0
+#define        CS5536_ACPI_LENGTH      0x20
+#define        CS5536_PMS_RANGE        0xffffff80
+#define        CS5536_PMS_LENGTH       0x80
+/* IO space for IDE */
+#define        CS5536_IDE_RANGE        0xfffffff0
+#define        CS5536_IDE_LENGTH       0x10
+/* IO space for ACC */
+#define        CS5536_ACC_RANGE        0xffffff80
+#define        CS5536_ACC_LENGTH       0x80
+/* MEM space for ALL USB modules */
+#define        CS5536_OHCI_RANGE       0xfffff000
+#define        CS5536_OHCI_LENGTH      0x1000
+#define        CS5536_EHCI_RANGE       0xfffff000
+#define        CS5536_EHCI_LENGTH      0x1000
+
+/*
+ * PCI MSR ACCESS
+ */
+#define        PCI_MSR_CTRL            0xF0
+#define        PCI_MSR_ADDR            0xF4
+#define        PCI_MSR_DATA_LO         0xF8
+#define        PCI_MSR_DATA_HI         0xFC
+
+/**************** MSR *****************************/
+
+/*
+ * GLIU STANDARD MSR
+ */
+#define        GLIU_CAP                0x00
+#define        GLIU_CONFIG             0x01
+#define        GLIU_SMI                0x02
+#define        GLIU_ERROR              0x03
+#define        GLIU_PM                 0x04
+#define        GLIU_DIAG               0x05
+
+/*
+ * GLIU SPEC. MSR
+ */
+#define        GLIU_P2D_BM0            0x20
+#define        GLIU_P2D_BM1            0x21
+#define        GLIU_P2D_BM2            0x22
+#define        GLIU_P2D_BMK0           0x23
+#define        GLIU_P2D_BMK1           0x24
+#define        GLIU_P2D_BM3            0x25
+#define        GLIU_P2D_BM4            0x26
+#define        GLIU_COH                0x80
+#define        GLIU_PAE                0x81
+#define        GLIU_ARB                0x82
+#define        GLIU_ASMI               0x83
+#define        GLIU_AERR               0x84
+#define        GLIU_DEBUG              0x85
+#define        GLIU_PHY_CAP            0x86
+#define        GLIU_NOUT_RESP          0x87
+#define        GLIU_NOUT_WDATA         0x88
+#define        GLIU_WHOAMI             0x8B
+#define        GLIU_SLV_DIS            0x8C
+#define        GLIU_IOD_BM0            0xE0
+#define        GLIU_IOD_BM1            0xE1
+#define        GLIU_IOD_BM2            0xE2
+#define        GLIU_IOD_BM3            0xE3
+#define        GLIU_IOD_BM4            0xE4
+#define        GLIU_IOD_BM5            0xE5
+#define        GLIU_IOD_BM6            0xE6
+#define        GLIU_IOD_BM7            0xE7
+#define        GLIU_IOD_BM8            0xE8
+#define        GLIU_IOD_BM9            0xE9
+#define        GLIU_IOD_SC0            0xEA
+#define        GLIU_IOD_SC1            0xEB
+#define        GLIU_IOD_SC2            0xEC
+#define        GLIU_IOD_SC3            0xED
+#define        GLIU_IOD_SC4            0xEE
+#define        GLIU_IOD_SC5            0xEF
+#define        GLIU_IOD_SC6            0xF0
+#define        GLIU_IOD_SC7            0xF1
+
+/*
+ * SB STANDARD
+ */
+#define        SB_CAP          0x00
+#define        SB_CONFIG       0x01
+#define        SB_SMI          0x02
+#define        SB_ERROR        0x03
+#define        SB_MAR_ERR_EN           0x00000001
+#define        SB_TAR_ERR_EN           0x00000002
+#define        SB_RSVD_BIT1            0x00000004
+#define        SB_EXCEP_ERR_EN         0x00000008
+#define        SB_SYSE_ERR_EN          0x00000010
+#define        SB_PARE_ERR_EN          0x00000020
+#define        SB_TAS_ERR_EN           0x00000040
+#define        SB_MAR_ERR_FLAG         0x00010000
+#define        SB_TAR_ERR_FLAG         0x00020000
+#define        SB_RSVD_BIT2            0x00040000
+#define        SB_EXCEP_ERR_FLAG       0x00080000
+#define        SB_SYSE_ERR_FLAG        0x00100000
+#define        SB_PARE_ERR_FLAG        0x00200000
+#define        SB_TAS_ERR_FLAG         0x00400000
+#define        SB_PM           0x04
+#define        SB_DIAG         0x05
+
+/*
+ * SB SPEC.
+ */
+#define        SB_CTRL         0x10
+#define        SB_R0           0x20
+#define        SB_R1           0x21
+#define        SB_R2           0x22
+#define        SB_R3           0x23
+#define        SB_R4           0x24
+#define        SB_R5           0x25
+#define        SB_R6           0x26
+#define        SB_R7           0x27
+#define        SB_R8           0x28
+#define        SB_R9           0x29
+#define        SB_R10          0x2A
+#define        SB_R11          0x2B
+#define        SB_R12          0x2C
+#define        SB_R13          0x2D
+#define        SB_R14          0x2E
+#define        SB_R15          0x2F
+
+/*
+ * GLCP STANDARD
+ */
+#define        GLCP_CAP                0x00
+#define        GLCP_CONFIG             0x01
+#define        GLCP_SMI                0x02
+#define        GLCP_ERROR              0x03
+#define        GLCP_PM                 0x04
+#define        GLCP_DIAG               0x05
+
+/*
+ * GLCP SPEC.
+ */
+#define        GLCP_CLK_DIS_DELAY      0x08
+#define        GLCP_PM_CLK_DISABLE     0x09
+#define        GLCP_GLB_PM             0x0B
+#define        GLCP_DBG_OUT            0x0C
+#define        GLCP_RSVD1              0x0D
+#define        GLCP_SOFT_COM           0x0E
+#define        SOFT_BAR_SMB_FLAG       0x00000001
+#define        SOFT_BAR_GPIO_FLAG      0x00000002
+#define        SOFT_BAR_MFGPT_FLAG     0x00000004
+#define        SOFT_BAR_IRQ_FLAG       0x00000008
+#define        SOFT_BAR_PMS_FLAG       0x00000010
+#define        SOFT_BAR_ACPI_FLAG      0x00000020
+#define        SOFT_BAR_IDE_FLAG       0x00000400
+#define        SOFT_BAR_ACC_FLAG       0x00000800
+#define        SOFT_BAR_OHCI_FLAG      0x00001000
+#define        SOFT_BAR_EHCI_FLAG      0x00002000
+#define        GLCP_RSVD2              0x0F
+#define        GLCP_CLK_OFF            0x10
+#define        GLCP_CLK_ACTIVE         0x11
+#define        GLCP_CLK_DISABLE        0x12
+#define        GLCP_CLK4ACK            0x13
+#define        GLCP_SYS_RST            0x14
+#define        GLCP_RSVD3              0x15
+#define        GLCP_DBG_CLK_CTRL       0x16
+#define        GLCP_CHIP_REV_ID        0x17
+
+/* PIC */
+#define        PIC_YSEL_LOW            0x20
+#define        PIC_YSEL_LOW_USB_SHIFT          8
+#define        PIC_YSEL_LOW_ACC_SHIFT          16
+#define        PIC_YSEL_LOW_FLASH_SHIFT        24
+#define        PIC_YSEL_HIGH           0x21
+#define        PIC_ZSEL_LOW            0x22
+#define        PIC_ZSEL_HIGH           0x23
+#define        PIC_IRQM_PRIM           0x24
+#define        PIC_IRQM_LPC            0x25
+#define        PIC_XIRR_STS_LOW        0x26
+#define        PIC_XIRR_STS_HIGH       0x27
+#define        PCI_SHDW                0x34
+
+/*
+ * DIVIL STANDARD
+ */
+#define        DIVIL_CAP               0x00
+#define        DIVIL_CONFIG            0x01
+#define        DIVIL_SMI               0x02
+#define        DIVIL_ERROR             0x03
+#define        DIVIL_PM                0x04
+#define        DIVIL_DIAG              0x05
+
+/*
+ * DIVIL SPEC.
+ */
+#define        DIVIL_LBAR_IRQ          0x08
+#define        DIVIL_LBAR_KEL          0x09
+#define        DIVIL_LBAR_SMB          0x0B
+#define        DIVIL_LBAR_GPIO         0x0C
+#define        DIVIL_LBAR_MFGPT        0x0D
+#define        DIVIL_LBAR_ACPI         0x0E
+#define        DIVIL_LBAR_PMS          0x0F
+#define        DIVIL_LEG_IO            0x14
+#define        DIVIL_BALL_OPTS         0x15
+#define        DIVIL_SOFT_IRQ          0x16
+#define        DIVIL_SOFT_RESET        0x17
+
+/* MFGPT */
+#define MFGPT_IRQ      0x28
+
+/*
+ * IDE STANDARD
+ */
+#define        IDE_CAP         0x00
+#define        IDE_CONFIG      0x01
+#define        IDE_SMI         0x02
+#define        IDE_ERROR       0x03
+#define        IDE_PM          0x04
+#define        IDE_DIAG        0x05
+
+/*
+ * IDE SPEC.
+ */
+#define        IDE_IO_BAR      0x08
+#define        IDE_CFG         0x10
+#define        IDE_DTC         0x12
+#define        IDE_CAST        0x13
+#define        IDE_ETC         0x14
+#define        IDE_INTERNAL_PM 0x15
+
+/*
+ * ACC STANDARD
+ */
+#define        ACC_CAP         0x00
+#define        ACC_CONFIG      0x01
+#define        ACC_SMI         0x02
+#define        ACC_ERROR       0x03
+#define        ACC_PM          0x04
+#define        ACC_DIAG        0x05
+
+/*
+ * USB STANDARD
+ */
+#define        USB_CAP         0x00
+#define        USB_CONFIG      0x01
+#define        USB_SMI         0x02
+#define        USB_ERROR       0x03
+#define        USB_PM          0x04
+#define        USB_DIAG        0x05
+
+/*
+ * USB SPEC.
+ */
+#define        USB_OHCI        0x08
+#define        USB_EHCI        0x09
+
+/****************** NATIVE ***************************/
+/* GPIO : I/O SPACE; REG : 32BITS */
+#define        GPIOL_OUT_VAL           0x00
+#define        GPIOL_OUT_EN            0x04
+
+#endif                         /* _CS5536_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
new file mode 100644 (file)
index 0000000..4b493d6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * cs5536 mfgpt header file
+ */
+
+#ifndef _CS5536_MFGPT_H
+#define _CS5536_MFGPT_H
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+#ifdef CONFIG_CS5536_MFGPT
+extern void setup_mfgpt0_timer(void);
+extern void disable_mfgpt0_counter(void);
+extern void enable_mfgpt0_counter(void);
+#else
+static inline void __maybe_unused setup_mfgpt0_timer(void)
+{
+}
+static inline void __maybe_unused disable_mfgpt0_counter(void)
+{
+}
+static inline void __maybe_unused enable_mfgpt0_counter(void)
+{
+}
+#endif
+
+#define MFGPT_TICK_RATE 14318000
+#define COMPARE  ((MFGPT_TICK_RATE + HZ/2) / HZ)
+
+#define MFGPT_BASE     mfgpt_base
+#define MFGPT0_CMP2    (MFGPT_BASE + 2)
+#define MFGPT0_CNT     (MFGPT_BASE + 4)
+#define MFGPT0_SETUP   (MFGPT_BASE + 6)
+
+#endif /*!_CS5536_MFGPT_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
new file mode 100644 (file)
index 0000000..0dca9c8
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * the definition file of cs5536 Virtual Support Module(VSM).
+ * pci configuration space can be accessed through the VSM, so
+ * there is no need of the MSR read/write now, except the spec.
+ * MSR registers which are not implemented yet.
+ *
+ * Copyright (C) 2007 Lemote Inc.
+ * Author : jlliu, liujl@lemote.com
+ */
+
+#ifndef        _CS5536_PCI_H
+#define        _CS5536_PCI_H
+
+#include <linux/types.h>
+#include <linux/pci_regs.h>
+
+extern void cs5536_pci_conf_write4(int function, int reg, u32 value);
+extern u32 cs5536_pci_conf_read4(int function, int reg);
+
+#define        CS5536_ACC_INTR         9
+#define        CS5536_IDE_INTR         14
+#define        CS5536_USB_INTR         11
+#define        CS5536_MFGPT_INTR       5
+#define        CS5536_UART1_INTR       4
+#define        CS5536_UART2_INTR       3
+
+/************** PCI BUS DEVICE FUNCTION ***************/
+
+/*
+ * PCI bus device function
+ */
+#define        PCI_BUS_CS5536          0
+#define        PCI_IDSEL_CS5536        14
+
+/********** STANDARD PCI-2.2 EXPANSION ****************/
+
+/*
+ * PCI configuration space
+ * we have to virtualize the PCI configure space head, so we should
+ * define the necessary IDs and some others.
+ */
+
+/* CONFIG of PCI VENDOR ID*/
+#define CFG_PCI_VENDOR_ID(mod_dev_id, sys_vendor_id) \
+       (((mod_dev_id) << 16) | (sys_vendor_id))
+
+/* VENDOR ID */
+#define        CS5536_VENDOR_ID        0x1022
+
+/* DEVICE ID */
+#define        CS5536_ISA_DEVICE_ID            0x2090
+#define        CS5536_IDE_DEVICE_ID            0x209a
+#define        CS5536_ACC_DEVICE_ID            0x2093
+#define        CS5536_OHCI_DEVICE_ID           0x2094
+#define        CS5536_EHCI_DEVICE_ID           0x2095
+
+/* CLASS CODE : CLASS SUB-CLASS INTERFACE */
+#define        CS5536_ISA_CLASS_CODE           0x060100
+#define CS5536_IDE_CLASS_CODE          0x010180
+#define        CS5536_ACC_CLASS_CODE           0x040100
+#define        CS5536_OHCI_CLASS_CODE          0x0C0310
+#define        CS5536_EHCI_CLASS_CODE          0x0C0320
+
+/* BHLC : BIST HEADER-TYPE LATENCY-TIMER CACHE-LINE-SIZE */
+
+#define CFG_PCI_CACHE_LINE_SIZE(header_type, latency_timer)    \
+       ((PCI_NONE_BIST << 24) | ((header_type) << 16) \
+               | ((latency_timer) << 8) | PCI_NORMAL_CACHE_LINE_SIZE);
+
+#define        PCI_NONE_BIST                   0x00    /* RO not implemented yet. */
+#define        PCI_BRIDGE_HEADER_TYPE          0x80    /* RO */
+#define        PCI_NORMAL_HEADER_TYPE          0x00
+#define        PCI_NORMAL_LATENCY_TIMER        0x00
+#define        PCI_NORMAL_CACHE_LINE_SIZE      0x08    /* RW */
+
+/* BAR */
+#define        PCI_BAR0_REG                    0x10
+#define        PCI_BAR1_REG                    0x14
+#define        PCI_BAR2_REG                    0x18
+#define        PCI_BAR3_REG                    0x1c
+#define        PCI_BAR4_REG                    0x20
+#define        PCI_BAR5_REG                    0x24
+#define        PCI_BAR_COUNT                   6
+#define        PCI_BAR_RANGE_MASK              0xFFFFFFFF
+
+/* CARDBUS CIS POINTER */
+#define        PCI_CARDBUS_CIS_POINTER         0x00000000
+
+/* SUBSYSTEM VENDOR ID  */
+#define        CS5536_SUB_VENDOR_ID            CS5536_VENDOR_ID
+
+/* SUBSYSTEM ID */
+#define        CS5536_ISA_SUB_ID               CS5536_ISA_DEVICE_ID
+#define        CS5536_IDE_SUB_ID               CS5536_IDE_DEVICE_ID
+#define        CS5536_ACC_SUB_ID               CS5536_ACC_DEVICE_ID
+#define        CS5536_OHCI_SUB_ID              CS5536_OHCI_DEVICE_ID
+#define        CS5536_EHCI_SUB_ID              CS5536_EHCI_DEVICE_ID
+
+/* EXPANSION ROM BAR */
+#define        PCI_EXPANSION_ROM_BAR           0x00000000
+
+/* CAPABILITIES POINTER */
+#define        PCI_CAPLIST_POINTER             0x00000000
+#define PCI_CAPLIST_USB_POINTER                0x40
+/* INTERRUPT */
+
+#define CFG_PCI_INTERRUPT_LINE(pin, mod_intr) \
+       ((PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | \
+               ((pin) << 8) | (mod_intr))
+
+#define        PCI_MAX_LATENCY                 0x40
+#define        PCI_MIN_GRANT                   0x00
+#define        PCI_DEFAULT_PIN                 0x01
+
+/*********** EXPANSION PCI REG ************************/
+
+/*
+ * ISA EXPANSION
+ */
+#define        PCI_UART1_INT_REG       0x50
+#define PCI_UART2_INT_REG      0x54
+#define        PCI_ISA_FIXUP_REG       0x58
+
+/*
+ * IDE EXPANSION
+ */
+#define        PCI_IDE_CFG_REG         0x40
+#define        CS5536_IDE_FLASH_SIGNATURE      0xDEADBEEF
+#define        PCI_IDE_DTC_REG         0x48
+#define        PCI_IDE_CAST_REG        0x4C
+#define        PCI_IDE_ETC_REG         0x50
+#define        PCI_IDE_PM_REG          0x54
+#define        PCI_IDE_INT_REG         0x60
+
+/*
+ * ACC EXPANSION
+ */
+#define        PCI_ACC_INT_REG         0x50
+
+/*
+ * OHCI EXPANSION : INTTERUPT IS IMPLEMENTED BY THE OHCI
+ */
+#define        PCI_OHCI_PM_REG         0x40
+#define        PCI_OHCI_INT_REG        0x50
+
+/*
+ * EHCI EXPANSION
+ */
+#define        PCI_EHCI_LEGSMIEN_REG   0x50
+#define        PCI_EHCI_LEGSMISTS_REG  0x54
+#define        PCI_EHCI_FLADJ_REG      0x60
+
+#endif                         /* _CS5536_PCI_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
new file mode 100644 (file)
index 0000000..6305bea
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * the read/write interfaces for Virtual Support Module(VSM)
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef        _CS5536_VSM_H
+#define        _CS5536_VSM_H
+
+#include <linux/types.h>
+
+typedef void (*cs5536_pci_vsm_write)(int reg, u32 value);
+typedef u32 (*cs5536_pci_vsm_read)(int reg);
+
+#define DECLARE_CS5536_MODULE(name) \
+extern void pci_##name##_write_reg(int reg, u32 value); \
+extern u32 pci_##name##_read_reg(int reg);
+
+/* ide module */
+DECLARE_CS5536_MODULE(ide)
+/* acc module */
+DECLARE_CS5536_MODULE(acc)
+/* ohci module */
+DECLARE_CS5536_MODULE(ohci)
+/* isa module */
+DECLARE_CS5536_MODULE(isa)
+/* ehci module */
+DECLARE_CS5536_MODULE(ehci)
+
+#endif                         /* _CS5536_VSM_H */
index 71a6851..981c75f 100644 (file)
@@ -28,7 +28,11 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
        dma_addr_t dma_addr)
 {
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+       return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
+#else
        return dma_addr & 0x7fffffff;
+#endif
 }
 
 static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
index da70bcf..ee8bc83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -15,9 +15,6 @@
 #include <linux/io.h>
 #include <linux/init.h>
 
-/* there is an internal bonito64-compatiable northbridge in loongson2e/2f */
-#include <asm/mips-boards/bonito64.h>
-
 /* loongson internal northbridge initialization */
 extern void bonito_irq_init(void);
 
@@ -32,7 +29,19 @@ extern unsigned long memsize, highmemsize;
 /* loongson-specific command line, env and memory initialization */
 extern void __init prom_init_memory(void);
 extern void __init prom_init_cmdline(void);
+extern void __init prom_init_machtype(void);
 extern void __init prom_init_env(void);
+#ifdef CONFIG_LOONGSON_UART_BASE
+extern unsigned long _loongson_uart_base, loongson_uart_base;
+extern void prom_init_loongson_uart_base(void);
+#endif
+
+static inline void prom_init_uart_base(void)
+{
+#ifdef CONFIG_LOONGSON_UART_BASE
+       prom_init_loongson_uart_base();
+#endif
+}
 
 /* irq operation functions */
 extern void bonito_irqdispatch(void);
@@ -40,25 +49,276 @@ extern void __init bonito_irq_init(void);
 extern void __init set_irq_trigger_mode(void);
 extern void __init mach_init_irq(void);
 extern void mach_irq_dispatch(unsigned int pending);
+extern int mach_i8259_irq(void);
+
+/* We need this in some places... */
+#define delay()        ({              \
+       int x;                          \
+       for (x = 0; x < 100000; x++)    \
+               __asm__ __volatile__(""); \
+})
+
+#define LOONGSON_REG(x) \
+       (*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
+
+#define LOONGSON_IRQ_BASE      32
+#define LOONGSON2_PERFCNT_IRQ  (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
+
+#define LOONGSON_FLASH_BASE    0x1c000000
+#define LOONGSON_FLASH_SIZE    0x02000000      /* 32M */
+#define LOONGSON_FLASH_TOP     (LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1)
+
+#define LOONGSON_LIO0_BASE     0x1e000000
+#define LOONGSON_LIO0_SIZE     0x01C00000      /* 28M */
+#define LOONGSON_LIO0_TOP      (LOONGSON_LIO0_BASE+LOONGSON_LIO0_SIZE-1)
+
+#define LOONGSON_BOOT_BASE     0x1fc00000
+#define LOONGSON_BOOT_SIZE     0x00100000      /* 1M */
+#define LOONGSON_BOOT_TOP      (LOONGSON_BOOT_BASE+LOONGSON_BOOT_SIZE-1)
+#define LOONGSON_REG_BASE      0x1fe00000
+#define LOONGSON_REG_SIZE      0x00100000      /* 256Bytes + 256Bytes + ??? */
+#define LOONGSON_REG_TOP       (LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
+
+#define LOONGSON_LIO1_BASE     0x1ff00000
+#define LOONGSON_LIO1_SIZE     0x00100000      /* 1M */
+#define LOONGSON_LIO1_TOP      (LOONGSON_LIO1_BASE+LOONGSON_LIO1_SIZE-1)
+
+#define LOONGSON_PCILO0_BASE   0x10000000
+#define LOONGSON_PCILO1_BASE   0x14000000
+#define LOONGSON_PCILO2_BASE   0x18000000
+#define LOONGSON_PCILO_BASE    LOONGSON_PCILO0_BASE
+#define LOONGSON_PCILO_SIZE    0x0c000000      /* 64M * 3 */
+#define LOONGSON_PCILO_TOP     (LOONGSON_PCILO0_BASE+LOONGSON_PCILO_SIZE-1)
+
+#define LOONGSON_PCICFG_BASE   0x1fe80000
+#define LOONGSON_PCICFG_SIZE   0x00000800      /* 2K */
+#define LOONGSON_PCICFG_TOP    (LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
+#define LOONGSON_PCIIO_BASE    0x1fd00000
+#define LOONGSON_PCIIO_SIZE    0x00100000      /* 1M */
+#define LOONGSON_PCIIO_TOP     (LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
+
+/* Loongson Register Bases */
+
+#define LOONGSON_PCICONFIGBASE 0x00
+#define LOONGSON_REGBASE       0x100
 
 /* PCI Configuration Registers */
-#define LOONGSON_PCI_ISR4C  BONITO_PCI_REG(0x4c)
+
+#define LOONGSON_PCI_REG(x)    LOONGSON_REG(LOONGSON_PCICONFIGBASE + (x))
+#define LOONGSON_PCIDID                LOONGSON_PCI_REG(0x00)
+#define LOONGSON_PCICMD                LOONGSON_PCI_REG(0x04)
+#define LOONGSON_PCICLASS      LOONGSON_PCI_REG(0x08)
+#define LOONGSON_PCILTIMER     LOONGSON_PCI_REG(0x0c)
+#define LOONGSON_PCIBASE0      LOONGSON_PCI_REG(0x10)
+#define LOONGSON_PCIBASE1      LOONGSON_PCI_REG(0x14)
+#define LOONGSON_PCIBASE2      LOONGSON_PCI_REG(0x18)
+#define LOONGSON_PCIBASE3      LOONGSON_PCI_REG(0x1c)
+#define LOONGSON_PCIBASE4      LOONGSON_PCI_REG(0x20)
+#define LOONGSON_PCIEXPRBASE   LOONGSON_PCI_REG(0x30)
+#define LOONGSON_PCIINT                LOONGSON_PCI_REG(0x3c)
+
+#define LOONGSON_PCI_ISR4C     LOONGSON_PCI_REG(0x4c)
+
+#define LOONGSON_PCICMD_PERR_CLR       0x80000000
+#define LOONGSON_PCICMD_SERR_CLR       0x40000000
+#define LOONGSON_PCICMD_MABORT_CLR     0x20000000
+#define LOONGSON_PCICMD_MTABORT_CLR    0x10000000
+#define LOONGSON_PCICMD_TABORT_CLR     0x08000000
+#define LOONGSON_PCICMD_MPERR_CLR      0x01000000
+#define LOONGSON_PCICMD_PERRRESPEN     0x00000040
+#define LOONGSON_PCICMD_ASTEPEN                0x00000080
+#define LOONGSON_PCICMD_SERREN         0x00000100
+#define LOONGSON_PCILTIMER_BUSLATENCY  0x0000ff00
+#define LOONGSON_PCILTIMER_BUSLATENCY_SHIFT    8
+
+/* Loongson h/w Configuration */
+
+#define LOONGSON_GENCFG_OFFSET         0x4
+#define LOONGSON_GENCFG        LOONGSON_REG(LOONGSON_REGBASE + LOONGSON_GENCFG_OFFSET)
+
+#define LOONGSON_GENCFG_DEBUGMODE      0x00000001
+#define LOONGSON_GENCFG_SNOOPEN                0x00000002
+#define LOONGSON_GENCFG_CPUSELFRESET   0x00000004
+
+#define LOONGSON_GENCFG_FORCE_IRQA     0x00000008
+#define LOONGSON_GENCFG_IRQA_ISOUT     0x00000010
+#define LOONGSON_GENCFG_IRQA_FROM_INT1 0x00000020
+#define LOONGSON_GENCFG_BYTESWAP       0x00000040
+
+#define LOONGSON_GENCFG_UNCACHED       0x00000080
+#define LOONGSON_GENCFG_PREFETCHEN     0x00000100
+#define LOONGSON_GENCFG_WBEHINDEN      0x00000200
+#define LOONGSON_GENCFG_CACHEALG       0x00000c00
+#define LOONGSON_GENCFG_CACHEALG_SHIFT 10
+#define LOONGSON_GENCFG_PCIQUEUE       0x00001000
+#define LOONGSON_GENCFG_CACHESTOP      0x00002000
+#define LOONGSON_GENCFG_MSTRBYTESWAP   0x00004000
+#define LOONGSON_GENCFG_BUSERREN       0x00008000
+#define LOONGSON_GENCFG_NORETRYTIMEOUT 0x00010000
+#define LOONGSON_GENCFG_SHORTCOPYTIMEOUT       0x00020000
+
+/* PCI address map control */
+
+#define LOONGSON_PCIMAP                        LOONGSON_REG(LOONGSON_REGBASE + 0x10)
+#define LOONGSON_PCIMEMBASECFG         LOONGSON_REG(LOONGSON_REGBASE + 0x14)
+#define LOONGSON_PCIMAP_CFG            LOONGSON_REG(LOONGSON_REGBASE + 0x18)
+
+/* GPIO Regs - r/w */
+
+#define LOONGSON_GPIODATA              LOONGSON_REG(LOONGSON_REGBASE + 0x1c)
+#define LOONGSON_GPIOIE                        LOONGSON_REG(LOONGSON_REGBASE + 0x20)
+
+/* ICU Configuration Regs - r/w */
+
+#define LOONGSON_INTEDGE               LOONGSON_REG(LOONGSON_REGBASE + 0x24)
+#define LOONGSON_INTSTEER              LOONGSON_REG(LOONGSON_REGBASE + 0x28)
+#define LOONGSON_INTPOL                        LOONGSON_REG(LOONGSON_REGBASE + 0x2c)
+
+/* ICU Enable Regs - IntEn & IntISR are r/o. */
+
+#define LOONGSON_INTENSET              LOONGSON_REG(LOONGSON_REGBASE + 0x30)
+#define LOONGSON_INTENCLR              LOONGSON_REG(LOONGSON_REGBASE + 0x34)
+#define LOONGSON_INTEN                 LOONGSON_REG(LOONGSON_REGBASE + 0x38)
+#define LOONGSON_INTISR                        LOONGSON_REG(LOONGSON_REGBASE + 0x3c)
+
+/* ICU */
+#define LOONGSON_ICU_MBOXES            0x0000000f
+#define LOONGSON_ICU_MBOXES_SHIFT      0
+#define LOONGSON_ICU_DMARDY            0x00000010
+#define LOONGSON_ICU_DMAEMPTY          0x00000020
+#define LOONGSON_ICU_COPYRDY           0x00000040
+#define LOONGSON_ICU_COPYEMPTY         0x00000080
+#define LOONGSON_ICU_COPYERR           0x00000100
+#define LOONGSON_ICU_PCIIRQ            0x00000200
+#define LOONGSON_ICU_MASTERERR         0x00000400
+#define LOONGSON_ICU_SYSTEMERR         0x00000800
+#define LOONGSON_ICU_DRAMPERR          0x00001000
+#define LOONGSON_ICU_RETRYERR          0x00002000
+#define LOONGSON_ICU_GPIOS             0x01ff0000
+#define LOONGSON_ICU_GPIOS_SHIFT               16
+#define LOONGSON_ICU_GPINS             0x7e000000
+#define LOONGSON_ICU_GPINS_SHIFT               25
+#define LOONGSON_ICU_MBOX(N)           (1<<(LOONGSON_ICU_MBOXES_SHIFT+(N)))
+#define LOONGSON_ICU_GPIO(N)           (1<<(LOONGSON_ICU_GPIOS_SHIFT+(N)))
+#define LOONGSON_ICU_GPIN(N)           (1<<(LOONGSON_ICU_GPINS_SHIFT+(N)))
+
+/* PCI prefetch window base & mask */
+
+#define LOONGSON_MEM_WIN_BASE_L        LOONGSON_REG(LOONGSON_REGBASE + 0x40)
+#define LOONGSON_MEM_WIN_BASE_H        LOONGSON_REG(LOONGSON_REGBASE + 0x44)
+#define LOONGSON_MEM_WIN_MASK_L        LOONGSON_REG(LOONGSON_REGBASE + 0x48)
+#define LOONGSON_MEM_WIN_MASK_H        LOONGSON_REG(LOONGSON_REGBASE + 0x4c)
 
 /* PCI_Hit*_Sel_* */
 
-#define LOONGSON_PCI_HIT0_SEL_L     BONITO(BONITO_REGBASE + 0x50)
-#define LOONGSON_PCI_HIT0_SEL_H     BONITO(BONITO_REGBASE + 0x54)
-#define LOONGSON_PCI_HIT1_SEL_L     BONITO(BONITO_REGBASE + 0x58)
-#define LOONGSON_PCI_HIT1_SEL_H     BONITO(BONITO_REGBASE + 0x5c)
-#define LOONGSON_PCI_HIT2_SEL_L     BONITO(BONITO_REGBASE + 0x60)
-#define LOONGSON_PCI_HIT2_SEL_H     BONITO(BONITO_REGBASE + 0x64)
+#define LOONGSON_PCI_HIT0_SEL_L                LOONGSON_REG(LOONGSON_REGBASE + 0x50)
+#define LOONGSON_PCI_HIT0_SEL_H                LOONGSON_REG(LOONGSON_REGBASE + 0x54)
+#define LOONGSON_PCI_HIT1_SEL_L                LOONGSON_REG(LOONGSON_REGBASE + 0x58)
+#define LOONGSON_PCI_HIT1_SEL_H                LOONGSON_REG(LOONGSON_REGBASE + 0x5c)
+#define LOONGSON_PCI_HIT2_SEL_L                LOONGSON_REG(LOONGSON_REGBASE + 0x60)
+#define LOONGSON_PCI_HIT2_SEL_H                LOONGSON_REG(LOONGSON_REGBASE + 0x64)
 
 /* PXArb Config & Status */
 
-#define LOONGSON_PXARB_CFG      BONITO(BONITO_REGBASE + 0x68)
-#define LOONGSON_PXARB_STATUS       BONITO(BONITO_REGBASE + 0x6c)
+#define LOONGSON_PXARB_CFG             LOONGSON_REG(LOONGSON_REGBASE + 0x68)
+#define LOONGSON_PXARB_STATUS          LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
+
+/* pcimap */
+
+#define LOONGSON_PCIMAP_PCIMAP_LO0     0x0000003f
+#define LOONGSON_PCIMAP_PCIMAP_LO0_SHIFT       0
+#define LOONGSON_PCIMAP_PCIMAP_LO1     0x00000fc0
+#define LOONGSON_PCIMAP_PCIMAP_LO1_SHIFT       6
+#define LOONGSON_PCIMAP_PCIMAP_LO2     0x0003f000
+#define LOONGSON_PCIMAP_PCIMAP_LO2_SHIFT       12
+#define LOONGSON_PCIMAP_PCIMAP_2       0x00040000
+#define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
+       ((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
+
+#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
+#include <linux/cpufreq.h>
+extern void loongson2_cpu_wait(void);
+extern struct cpufreq_frequency_table loongson2_clockmod_table[];
+
+/* Chip Config */
+#define LOONGSON_CHIPCFG0              LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#endif
+
+/*
+ * address windows configuration module
+ *
+ * loongson2e do not have this module
+ */
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+
+/* address window config module base address */
+#define LOONGSON_ADDRWINCFG_BASE               0x3ff00000ul
+#define LOONGSON_ADDRWINCFG_SIZE               0x180
+
+extern unsigned long _loongson_addrwincfg_base;
+#define LOONGSON_ADDRWINCFG(offset) \
+       (*(volatile u64 *)(_loongson_addrwincfg_base + (offset)))
+
+#define CPU_WIN0_BASE  LOONGSON_ADDRWINCFG(0x00)
+#define CPU_WIN1_BASE  LOONGSON_ADDRWINCFG(0x08)
+#define CPU_WIN2_BASE  LOONGSON_ADDRWINCFG(0x10)
+#define CPU_WIN3_BASE  LOONGSON_ADDRWINCFG(0x18)
+
+#define CPU_WIN0_MASK  LOONGSON_ADDRWINCFG(0x20)
+#define CPU_WIN1_MASK  LOONGSON_ADDRWINCFG(0x28)
+#define CPU_WIN2_MASK  LOONGSON_ADDRWINCFG(0x30)
+#define CPU_WIN3_MASK  LOONGSON_ADDRWINCFG(0x38)
+
+#define CPU_WIN0_MMAP  LOONGSON_ADDRWINCFG(0x40)
+#define CPU_WIN1_MMAP  LOONGSON_ADDRWINCFG(0x48)
+#define CPU_WIN2_MMAP  LOONGSON_ADDRWINCFG(0x50)
+#define CPU_WIN3_MMAP  LOONGSON_ADDRWINCFG(0x58)
+
+#define PCIDMA_WIN0_BASE       LOONGSON_ADDRWINCFG(0x60)
+#define PCIDMA_WIN1_BASE       LOONGSON_ADDRWINCFG(0x68)
+#define PCIDMA_WIN2_BASE       LOONGSON_ADDRWINCFG(0x70)
+#define PCIDMA_WIN3_BASE       LOONGSON_ADDRWINCFG(0x78)
+
+#define PCIDMA_WIN0_MASK       LOONGSON_ADDRWINCFG(0x80)
+#define PCIDMA_WIN1_MASK       LOONGSON_ADDRWINCFG(0x88)
+#define PCIDMA_WIN2_MASK       LOONGSON_ADDRWINCFG(0x90)
+#define PCIDMA_WIN3_MASK       LOONGSON_ADDRWINCFG(0x98)
+
+#define PCIDMA_WIN0_MMAP       LOONGSON_ADDRWINCFG(0xa0)
+#define PCIDMA_WIN1_MMAP       LOONGSON_ADDRWINCFG(0xa8)
+#define PCIDMA_WIN2_MMAP       LOONGSON_ADDRWINCFG(0xb0)
+#define PCIDMA_WIN3_MMAP       LOONGSON_ADDRWINCFG(0xb8)
+
+#define ADDRWIN_WIN0   0
+#define ADDRWIN_WIN1   1
+#define ADDRWIN_WIN2   2
+#define ADDRWIN_WIN3   3
+
+#define ADDRWIN_MAP_DST_DDR    0
+#define ADDRWIN_MAP_DST_PCI    1
+#define ADDRWIN_MAP_DST_LIO    1
+
+/*
+ * s: CPU, PCIDMA
+ * d: DDR, PCI, LIO
+ * win: 0, 1, 2, 3
+ * src: map source
+ * dst: map destination
+ * size: ~mask + 1
+ */
+#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
+       s##_WIN##w##_BASE = (src); \
+       s##_WIN##w##_MMAP = (src) | ADDRWIN_MAP_DST_##d; \
+       s##_WIN##w##_MASK = ~(size-1); \
+} while (0)
+
+#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
+#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
+#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
 
-/* loongson2-specific perf counter IRQ */
-#define LOONGSON2_PERFCNT_IRQ   (MIPS_CPU_IRQ_BASE + 6)
+#endif /* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */
 
 #endif /* __ASM_MACH_LOONGSON_LOONGSON_H */
index 206ea20..acf8359 100644 (file)
 
 #ifdef CONFIG_LEMOTE_FULOONG2E
 
-#define LOONGSON_UART_BASE (BONITO_PCIIO_BASE + 0x3f8)
-
 #define LOONGSON_MACHTYPE MACH_LEMOTE_FL2E
 
 #endif
 
+/* use fuloong2f as the default machine of LEMOTE_MACH2F */
+#ifdef CONFIG_LEMOTE_MACH2F
+
+#define LOONGSON_MACHTYPE MACH_LEMOTE_FL2F
+
+#endif
+
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
index bd7b3cb..e9960f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
 #define __ASM_MACH_LOONGSON_MEM_H
 
 /*
- * On Lemote Loongson 2e
+ * high memory space
  *
- * the high memory space starts from 512M.
- * the peripheral registers reside between 0x1000:0000 and 0x2000:0000.
+ * in loongson2e, starts from 512M
+ * in loongson2f, starts from 2G 256M
  */
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_HIGHMEM_START 0x20000000
+#else
+#define LOONGSON_HIGHMEM_START 0x90000000
+#endif
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-
-#define LOONGSON_HIGHMEM_START  0x20000000
+/*
+ * the peripheral registers(MMIO):
+ *
+ * On the Lemote Loongson 2e system, reside between 0x1000:0000 and 0x2000:0000.
+ * On the Lemote Loongson 2f system, reside between 0x1000:0000 and 0x8000:0000.
+ */
 
 #define LOONGSON_MMIO_MEM_START 0x10000000
-#define LOONGSON_MMIO_MEM_END   0x20000000
 
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_MMIO_MEM_END  0x20000000
+#else
+#define LOONGSON_MMIO_MEM_END  0x80000000
 #endif
 
 #endif /* __ASM_MACH_LOONGSON_MEM_H */
index f1663ca..a199a4f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008 Zhang Le <r0bertz@gentoo.org>
+ * Copyright (c) 2009 Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
 #ifndef __ASM_MACH_LOONGSON_PCI_H_
 #define __ASM_MACH_LOONGSON_PCI_H_
 
-extern struct pci_ops bonito64_pci_ops;
+extern struct pci_ops loongson_pci_ops;
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
+/* this is an offset from mips_io_port_base */
+#define LOONGSON_PCI_IO_START  0x00004000UL
+
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+
+/*
+ * we use address window2 to map cpu address space to pci space
+ * window2: cpu [1G, 2G] -> pci [1G, 2G]
+ * why not use window 0 & 1? because they are used by cpu when booting.
+ * window0: cpu [0, 256M] -> ddr [0, 256M]
+ * window1: cpu [256M, 512M] -> pci [256M, 512M]
+ */
+
+/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
+#define LOONGSON_CPU_MEM_SRC   0x40000000ul            /* 1G */
+#define LOONGSON_PCI_MEM_DST   LOONGSON_CPU_MEM_SRC
+
+#define LOONGSON_PCI_MEM_START LOONGSON_PCI_MEM_DST
+#define LOONGSON_PCI_MEM_END   (0x80000000ul-1)        /* 2G */
+
+#define MMAP_CPUTOPCI_SIZE     (LOONGSON_PCI_MEM_END - \
+                                       LOONGSON_PCI_MEM_START + 1)
+
+#else  /* loongson2f/32bit & loongson2e */
 
 /* this pci memory space is mapped by pcimap in pci.c */
-#define LOONGSON_PCI_MEM_START BONITO_PCILO1_BASE
-#define LOONGSON_PCI_MEM_END   (BONITO_PCILO1_BASE + 0x04000000 * 2)
+#define LOONGSON_PCI_MEM_START LOONGSON_PCILO1_BASE
+#define LOONGSON_PCI_MEM_END   (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
 /* this is an offset from mips_io_port_base */
 #define LOONGSON_PCI_IO_START  0x00004000UL
 
-#endif
+#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
 
 #endif /* !__ASM_MACH_LOONGSON_PCI_H_ */
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
new file mode 100644 (file)
index 0000000..bcad43a
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+
+#ifndef _ASM_MACH_POWERTV_ASIC_H
+#define _ASM_MACH_POWERTV_ASIC_H
+
+#include <linux/ioport.h>
+#include <asm/mach-powertv/asic_regs.h>
+
+#define DVR_CAPABLE     (1<<0)
+#define PCIE_CAPABLE    (1<<1)
+#define FFS_CAPABLE     (1<<2)
+#define DISPLAY_CAPABLE (1<<3)
+
+/* Platform Family types
+ * For compitability, the new value must be added in the end */
+enum family_type {
+       FAMILY_8500,
+       FAMILY_8500RNG,
+       FAMILY_4500,
+       FAMILY_1500,
+       FAMILY_8600,
+       FAMILY_4600,
+       FAMILY_4600VZA,
+       FAMILY_8600VZB,
+       FAMILY_1500VZE,
+       FAMILY_1500VZF,
+       FAMILIES
+};
+
+/* Register maps for each ASIC */
+extern const struct register_map calliope_register_map;
+extern const struct register_map cronus_register_map;
+extern const struct register_map zeus_register_map;
+
+extern struct resource dvr_cronus_resources[];
+extern struct resource dvr_zeus_resources[];
+extern struct resource non_dvr_calliope_resources[];
+extern struct resource non_dvr_cronus_resources[];
+extern struct resource non_dvr_cronuslite_resources[];
+extern struct resource non_dvr_vz_calliope_resources[];
+extern struct resource non_dvr_vze_calliope_resources[];
+extern struct resource non_dvr_vzf_calliope_resources[];
+extern struct resource non_dvr_zeus_resources[];
+
+extern void powertv_platform_init(void);
+extern void platform_alloc_bootmem(void);
+extern enum asic_type platform_get_asic(void);
+extern enum family_type platform_get_family(void);
+extern int platform_supports_dvr(void);
+extern int platform_supports_ffs(void);
+extern int platform_supports_pcie(void);
+extern int platform_supports_display(void);
+extern void configure_platform(void);
+extern void platform_configure_usb_ehci(void);
+extern void platform_unconfigure_usb_ehci(void);
+extern void platform_configure_usb_ohci(void);
+extern void platform_unconfigure_usb_ohci(void);
+
+/* Platform Resources */
+#define ASIC_RESOURCE_GET_EXISTS 1
+extern struct resource *asic_resource_get(const char *name);
+extern void platform_release_memory(void *baddr, int size);
+
+/* Reboot Cause */
+extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
+extern void set_locked_reboot_cause(char code, unsigned int data,
+       unsigned int data2);
+
+enum sys_reboot_type {
+       sys_unknown_reboot = 0x00,      /* Unknown reboot cause */
+       sys_davic_change = 0x01,        /* Reboot due to change in DAVIC
+                                        * mode */
+       sys_user_reboot = 0x02,         /* Reboot initiated by user */
+       sys_system_reboot = 0x03,       /* Reboot initiated by OS */
+       sys_trap_reboot = 0x04,         /* Reboot due to a CPU trap */
+       sys_silent_reboot = 0x05,       /* Silent reboot */
+       sys_boot_ldr_reboot = 0x06,     /* Bootloader reboot */
+       sys_power_up_reboot = 0x07,     /* Power on bootup.  Older
+                                        * drivers may report as
+                                        * userReboot. */
+       sys_code_change = 0x08,         /* Reboot to take code change.
+                                        * Older drivers may report as
+                                        * userReboot. */
+       sys_hardware_reset = 0x09,      /* HW watchdog or front-panel
+                                        * reset button reset.  Older
+                                        * drivers may report as
+                                        * userReboot. */
+       sys_watchdogInterrupt = 0x0A    /* Pre-watchdog interrupt */
+};
+
+#endif /* _ASM_MACH_POWERTV_ASIC_H */
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h
new file mode 100644 (file)
index 0000000..9a65c93
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+
+#ifndef __ASM_MACH_POWERTV_ASIC_H_
+#define __ASM_MACH_POWERTV_ASIC_H_
+#include <linux/io.h>
+
+/* ASIC types */
+enum asic_type {
+       ASIC_UNKNOWN,
+       ASIC_ZEUS,
+       ASIC_CALLIOPE,
+       ASIC_CRONUS,
+       ASIC_CRONUSLITE,
+       ASICS
+};
+
+/* hardcoded values read from Chip Version registers */
+#define CRONUS_10      0x0B4C1C20
+#define CRONUS_11      0x0B4C1C21
+#define CRONUSLITE_10  0x0B4C1C40
+
+#define NAND_FLASH_BASE        0x03000000
+#define ZEUS_IO_BASE   0x09000000
+#define CALLIOPE_IO_BASE       0x08000000
+#define CRONUS_IO_BASE 0x09000000
+#define ASIC_IO_SIZE   0x01000000
+
+/* Definitions for backward compatibility */
+#define UART1_INTSTAT  uart1_intstat
+#define UART1_INTEN    uart1_inten
+#define UART1_CONFIG1  uart1_config1
+#define UART1_CONFIG2  uart1_config2
+#define UART1_DIVISORHI        uart1_divisorhi
+#define UART1_DIVISORLO        uart1_divisorlo
+#define UART1_DATA     uart1_data
+#define UART1_STATUS   uart1_status
+
+/* ASIC register enumeration */
+struct register_map {
+       u32 eic_slow0_strt_add;
+       u32 eic_cfg_bits;
+       u32 eic_ready_status;
+
+       u32 chipver3;
+       u32 chipver2;
+       u32 chipver1;
+       u32 chipver0;
+
+       u32 uart1_intstat;
+       u32 uart1_inten;
+       u32 uart1_config1;
+       u32 uart1_config2;
+       u32 uart1_divisorhi;
+       u32 uart1_divisorlo;
+       u32 uart1_data;
+       u32 uart1_status;
+
+       u32 int_stat_3;
+       u32 int_stat_2;
+       u32 int_stat_1;
+       u32 int_stat_0;
+       u32 int_config;
+       u32 int_int_scan;
+       u32 ien_int_3;
+       u32 ien_int_2;
+       u32 ien_int_1;
+       u32 ien_int_0;
+       u32 int_level_3_3;
+       u32 int_level_3_2;
+       u32 int_level_3_1;
+       u32 int_level_3_0;
+       u32 int_level_2_3;
+       u32 int_level_2_2;
+       u32 int_level_2_1;
+       u32 int_level_2_0;
+       u32 int_level_1_3;
+       u32 int_level_1_2;
+       u32 int_level_1_1;
+       u32 int_level_1_0;
+       u32 int_level_0_3;
+       u32 int_level_0_2;
+       u32 int_level_0_1;
+       u32 int_level_0_0;
+       u32 int_docsis_en;
+
+       u32 mips_pll_setup;
+       u32 usb_fs;
+       u32 test_bus;
+       u32 crt_spare;
+       u32 usb2_ohci_int_mask;
+       u32 usb2_strap;
+       u32 ehci_hcapbase;
+       u32 ohci_hc_revision;
+       u32 bcm1_bs_lmi_steer;
+       u32 usb2_control;
+       u32 usb2_stbus_obc;
+       u32 usb2_stbus_mess_size;
+       u32 usb2_stbus_chunk_size;
+
+       u32 pcie_regs;
+       u32 tim_ch;
+       u32 tim_cl;
+       u32 gpio_dout;
+       u32 gpio_din;
+       u32 gpio_dir;
+       u32 watchdog;
+       u32 front_panel;
+
+       u32 register_maps;
+};
+
+extern enum asic_type asic;
+extern const struct register_map *register_map;
+extern unsigned long asic_phy_base;    /* Physical address of ASIC */
+extern unsigned long asic_base;                /* Virtual address of ASIC */
+
+/*
+ * Macros to interface to registers through their ioremapped address
+ * asic_reg_offset     Returns the offset of a given register from the start
+ *                     of the ASIC address space
+ * asic_reg_phys_addr  Returns the physical address of the given register
+ * asic_reg_addr       Returns the iomapped virtual address of the given
+ *                     register.
+ */
+#define asic_reg_offset(x)     (register_map->x)
+#define asic_reg_phys_addr(x)  (asic_phy_base + asic_reg_offset(x))
+#define asic_reg_addr(x) \
+       ((unsigned int *) (asic_base + asic_reg_offset(x)))
+
+/*
+ * The asic_reg macro is gone. It should be replaced by either asic_read or
+ * asic_write, as appropriate.
+ */
+
+#define asic_read(x)           readl(asic_reg_addr(x))
+#define asic_write(v, x)       writel(v, asic_reg_addr(x))
+
+extern void asic_irq_init(void);
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
new file mode 100644 (file)
index 0000000..5b8d5eb
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * Version from mach-generic modified to support PowerTV port
+ * Portions Copyright (C) 2009  Cisco Systems, Inc.
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+
+#ifndef __ASM_MACH_POWERTV_DMA_COHERENCE_H
+#define __ASM_MACH_POWERTV_DMA_COHERENCE_H
+
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <asm/mach-powertv/asic.h>
+
+static inline bool is_kseg2(void *addr)
+{
+       return (unsigned long)addr >= KSEG2;
+}
+
+static inline unsigned long virt_to_phys_from_pte(void *addr)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+
+       unsigned long virt_addr = (unsigned long)addr;
+       unsigned long phys_addr = 0UL;
+
+       /* get the page global directory. */
+       pgd = pgd_offset_k(virt_addr);
+
+       if (!pgd_none(*pgd)) {
+               /* get the page upper directory */
+               pud = pud_offset(pgd, virt_addr);
+               if (!pud_none(*pud)) {
+                       /* get the page middle directory */
+                       pmd = pmd_offset(pud, virt_addr);
+                       if (!pmd_none(*pmd)) {
+                               /* get a pointer to the page table entry */
+                               ptep = pte_offset(pmd, virt_addr);
+                               pte = *ptep;
+                               /* check for a valid page */
+                               if (pte_present(pte)) {
+                                       /* get the physical address the page is
+                                        * refering to */
+                                       phys_addr = (unsigned long)
+                                               page_to_phys(pte_page(pte));
+                                       /* add the offset within the page */
+                                       phys_addr |= (virt_addr & ~PAGE_MASK);
+                               }
+                       }
+               }
+       }
+
+       return phys_addr;
+}
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+       size_t size)
+{
+       if (is_kseg2(addr))
+               return phys_to_bus(virt_to_phys_from_pte(addr));
+       else
+               return phys_to_bus(virt_to_phys(addr));
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+       struct page *page)
+{
+       return phys_to_bus(page_to_phys(page));
+}
+
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+       dma_addr_t dma_addr)
+{
+       return bus_to_phys(dma_addr);
+}
+
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+       size_t size, enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+       /*
+        * we fall back to GFP_DMA when the mask isn't all 1s,
+        * so we can't guarantee allocations that must be
+        * within a tighter range than GFP_DMA..
+        */
+       if (mask < DMA_BIT_MASK(24))
+               return 0;
+
+       return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+       return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+                                        dma_addr_t dma_addr)
+{
+       return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+       return 0;
+}
+
+#endif /* __ASM_MACH_POWERTV_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-powertv/interrupts.h b/arch/mips/include/asm/mach-powertv/interrupts.h
new file mode 100644 (file)
index 0000000..629a574
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+
+#ifndef        _ASM_MACH_POWERTV_INTERRUPTS_H_
+#define _ASM_MACH_POWERTV_INTERRUPTS_H_
+
+/*
+ * Defines for all of the interrupt lines
+ */
+
+/* Definitions for backward compatibility */
+#define kIrq_Uart1             irq_uart1
+
+#define ibase 0
+
+/*------------- Register: int_stat_3 */
+/* 126 unused (bit 31) */
+#define irq_asc2video          (ibase+126)     /* ASC 2 Video Interrupt */
+#define irq_asc1video          (ibase+125)     /* ASC 1 Video Interrupt */
+#define irq_comms_block_wd     (ibase+124)     /* ASC 1 Video Interrupt */
+#define irq_fdma_mailbox       (ibase+123)     /* FDMA Mailbox Output */
+#define irq_fdma_gp            (ibase+122)     /* FDMA GP Output */
+#define irq_mips_pic           (ibase+121)     /* MIPS Performance Counter
+                                                * Interrupt */
+#define irq_mips_timer         (ibase+120)     /* MIPS Timer Interrupt */
+#define irq_memory_protect     (ibase+119)     /* Memory Protection Interrupt
+                                                * -- Ored by glue logic inside
+                                                *  SPARC ILC (see
+                                                *  INT_MEM_PROT_STAT, below,
+                                                *  for individual interrupts)
+                                                */
+/* 118 unused (bit 22) */
+#define irq_sbag               (ibase+117)     /* SBAG Interrupt -- Ored by
+                                                * glue logic inside SPARC ILC
+                                                * (see INT_SBAG_STAT, below,
+                                                * for individual interrupts) */
+#define irq_qam_b_fec          (ibase+116)     /* QAM  B FEC Interrupt */
+#define irq_qam_a_fec          (ibase+115)     /* QAM A FEC Interrupt */
+/* 114 unused  (bit 18) */
+#define irq_mailbox            (ibase+113)     /* Mailbox Debug Interrupt  --
+                                                * Ored by glue logic inside
+                                                * SPARC ILC (see
+                                                * INT_MAILBOX_STAT, below, for
+                                                * individual interrupts) */
+#define irq_fuse_stat1         (ibase+112)     /* Fuse Status 1 */
+#define irq_fuse_stat2         (ibase+111)     /* Fuse Status 2 */
+#define irq_fuse_stat3         (ibase+110)     /* Blitter Interrupt / Fuse
+                                                * Status 3 */
+#define irq_blitter            (ibase+110)     /* Blitter Interrupt / Fuse
+                                                * Status 3 */
+#define irq_avc1_pp0           (ibase+109)     /* AVC Decoder #1 PP0
+                                                * Interrupt */
+#define irq_avc1_pp1           (ibase+108)     /* AVC Decoder #1 PP1
+                                                * Interrupt */
+#define irq_avc1_mbe           (ibase+107)     /* AVC Decoder #1 MBE
+                                                * Interrupt */
+#define irq_avc2_pp0           (ibase+106)     /* AVC Decoder #2 PP0
+                                                * Interrupt */
+#define irq_avc2_pp1           (ibase+105)     /* AVC Decoder #2 PP1
+                                                * Interrupt */
+#define irq_avc2_mbe           (ibase+104)     /* AVC Decoder #2 MBE
+                                                * Interrupt */
+#define irq_zbug_spi           (ibase+103)     /* Zbug SPI Slave Interrupt */
+#define irq_qam_mod2           (ibase+102)     /* QAM Modulator 2 DMA
+                                                * Interrupt */
+#define irq_ir_rx              (ibase+101)     /* IR RX 2 Interrupt */
+#define irq_aud_dsp2           (ibase+100)     /* Audio DSP #2 Interrupt */
+#define irq_aud_dsp1           (ibase+99)      /* Audio DSP #1 Interrupt */
+#define irq_docsis             (ibase+98)      /* DOCSIS Debug Interrupt */
+#define irq_sd_dvp1            (ibase+97)      /* SD DVP #1 Interrupt */
+#define irq_sd_dvp2            (ibase+96)      /* SD DVP #2 Interrupt */
+/*------------- Register: int_stat_2 */
+#define irq_hd_dvp             (ibase+95)      /* HD DVP Interrupt */
+#define kIrq_Prewatchdog       (ibase+94)      /* watchdog Pre-Interrupt */
+#define irq_timer2             (ibase+93)      /* Programmable Timer
+                                                * Interrupt 2 */
+#define irq_1394               (ibase+92)      /* 1394 Firewire Interrupt */
+#define irq_usbohci            (ibase+91)      /* USB 2.0 OHCI Interrupt */
+#define irq_usbehci            (ibase+90)      /* USB 2.0 EHCI Interrupt */
+#define irq_pciexp             (ibase+89)      /* PCI Express 0 Interrupt */
+#define irq_pciexp0            (ibase+89)      /* PCI Express 0 Interrupt */
+#define irq_afe1               (ibase+88)      /* AFE 1 Interrupt */
+#define irq_sata               (ibase+87)      /* SATA 1 Interrupt */
+#define irq_sata1              (ibase+87)      /* SATA 1 Interrupt */
+#define irq_dtcp               (ibase+86)      /* DTCP Interrupt */
+#define irq_pciexp1            (ibase+85)      /* PCI Express 1 Interrupt */
+/* 84 unused   (bit 20) */
+/* 83 unused   (bit 19) */
+/* 82 unused   (bit 18) */
+#define irq_sata2              (ibase+81)      /* SATA2 Interrupt */
+#define irq_uart2              (ibase+80)      /* UART2 Interrupt */
+#define irq_legacy_usb         (ibase+79)      /* Legacy USB Host ISR (1.1
+                                                * Host module) */
+#define irq_pod                        (ibase+78)      /* POD Interrupt */
+#define irq_slave_usb          (ibase+77)      /* Slave USB */
+#define irq_denc1              (ibase+76)      /* DENC #1 VTG Interrupt */
+#define irq_vbi_vtg            (ibase+75)      /* VBI VTG Interrupt */
+#define irq_afe2               (ibase+74)      /* AFE 2 Interrupt */
+#define irq_denc2              (ibase+73)      /* DENC #2 VTG Interrupt */
+#define irq_asc2               (ibase+72)      /* ASC #2 Interrupt */
+#define irq_asc1               (ibase+71)      /* ASC #1 Interrupt */
+#define irq_mod_dma            (ibase+70)      /* Modulator DMA Interrupt */
+#define irq_byte_eng1          (ibase+69)      /* Byte Engine Interrupt [1] */
+#define irq_byte_eng0          (ibase+68)      /* Byte Engine Interrupt [0] */
+/* 67 unused   (bit 03) */
+/* 66 unused   (bit 02) */
+/* 65 unused   (bit 01) */
+/* 64 unused   (bit 00) */
+/*------------- Register: int_stat_1 */
+/* 63 unused   (bit 31) */
+/* 62 unused   (bit 30) */
+/* 61 unused   (bit 29) */
+/* 60 unused   (bit 28) */
+/* 59 unused   (bit 27) */
+/* 58 unused   (bit 26) */
+/* 57 unused   (bit 25) */
+/* 56 unused   (bit 24) */
+#define irq_buf_dma_mem2mem    (ibase+55)      /* BufDMA Memory to Memory
+                                                * Interrupt */
+#define irq_buf_dma_usbtransmit        (ibase+54)      /* BufDMA USB Transmit
+                                                * Interrupt */
+#define irq_buf_dma_qpskpodtransmit (ibase+53) /* BufDMA QPSK/POD Tramsit
+                                                * Interrupt */
+#define irq_buf_dma_transmit_error (ibase+52)  /* BufDMA Transmit Error
+                                                * Interrupt */
+#define irq_buf_dma_usbrecv    (ibase+51)      /* BufDMA USB Receive
+                                                * Interrupt */
+#define irq_buf_dma_qpskpodrecv        (ibase+50)      /* BufDMA QPSK/POD Receive
+                                                * Interrupt */
+#define irq_buf_dma_recv_error (ibase+49)      /* BufDMA Receive Error
+                                                * Interrupt */
+#define irq_qamdma_transmit_play (ibase+48)    /* QAMDMA Transmit/Play
+                                                * Interrupt */
+#define irq_qamdma_transmit_error (ibase+47)   /* QAMDMA Transmit Error
+                                                * Interrupt */
+#define irq_qamdma_recv2high   (ibase+46)      /* QAMDMA Receive 2 High
+                                                * (Chans 63-32) */
+#define irq_qamdma_recv2low    (ibase+45)      /* QAMDMA Receive 2 Low
+                                                * (Chans 31-0) */
+#define irq_qamdma_recv1high   (ibase+44)      /* QAMDMA Receive 1 High
+                                                * (Chans 63-32) */
+#define irq_qamdma_recv1low    (ibase+43)      /* QAMDMA Receive 1 Low
+                                                * (Chans 31-0) */
+#define irq_qamdma_recv_error  (ibase+42)      /* QAMDMA Receive Error
+                                                * Interrupt */
+#define irq_mpegsplice         (ibase+41)      /* MPEG Splice Interrupt */
+#define irq_deinterlace_rdy    (ibase+40)      /* Deinterlacer Frame Ready
+                                                * Interrupt */
+#define irq_ext_in0            (ibase+39)      /* External Interrupt irq_in0 */
+#define irq_gpio3              (ibase+38)      /* GP I/O IRQ 3 - From GP I/O
+                                                * Module */
+#define irq_gpio2              (ibase+37)      /* GP I/O IRQ 2 - From GP I/O
+                                                * Module (ABE_intN) */
+#define irq_pcrcmplt1          (ibase+36)      /* PCR Capture Complete  or
+                                                * Discontinuity 1 */
+#define irq_pcrcmplt2          (ibase+35)      /* PCR Capture Complete or
+                                                * Discontinuity 2 */
+#define irq_parse_peierr       (ibase+34)      /* PID Parser Error Detect
+                                                * (PEI) */
+#define irq_parse_cont_err     (ibase+33)      /* PID Parser continuity error
+                                                * detect */
+#define irq_ds1framer          (ibase+32)      /* DS1 Framer Interrupt */
+/*------------- Register: int_stat_0 */
+#define irq_gpio1              (ibase+31)      /* GP I/O IRQ 1 - From GP I/O
+                                                * Module */
+#define irq_gpio0              (ibase+30)      /* GP I/O IRQ 0 - From GP I/O
+                                                * Module */
+#define irq_qpsk_out_aloha     (ibase+29)      /* QPSK Output Slotted Aloha
+                                                * (chan 3) Transmission
+                                                * Completed OK */
+#define irq_qpsk_out_tdma      (ibase+28)      /* QPSK Output TDMA (chan 2)
+                                                * Transmission Completed OK */
+#define irq_qpsk_out_reserve   (ibase+27)      /* QPSK Output Reservation
+                                                * (chan 1) Transmission
+                                                * Completed OK */
+#define irq_qpsk_out_aloha_err (ibase+26)      /* QPSK Output Slotted Aloha
+                                                * (chan 3)Transmission
+                                                * completed with Errors. */
+#define irq_qpsk_out_tdma_err  (ibase+25)      /* QPSK Output TDMA (chan 2)
+                                                * Transmission completed with
+                                                * Errors. */
+#define irq_qpsk_out_rsrv_err  (ibase+24)      /* QPSK Output Reservation
+                                                * (chan 1) Transmission
+                                                * completed with Errors */
+#define irq_aloha_fail         (ibase+23)      /* Unsuccessful Resend of Aloha
+                                                * for N times. Aloha retry
+                                                * timeout for channel 3. */
+#define irq_timer1             (ibase+22)      /* Programmable Timer
+                                                * Interrupt */
+#define irq_keyboard           (ibase+21)      /* Keyboard Module Interrupt */
+#define irq_i2c                        (ibase+20)      /* I2C Module Interrupt */
+#define irq_spi                        (ibase+19)      /* SPI Module Interrupt */
+#define irq_irblaster          (ibase+18)      /* IR Blaster Interrupt */
+#define irq_splice_detect      (ibase+17)      /* PID Key Change Interrupt or
+                                                * Splice Detect Interrupt */
+#define irq_se_micro           (ibase+16)      /* Secure Micro I/F Module
+                                                * Interrupt */
+#define irq_uart1              (ibase+15)      /* UART Interrupt */
+#define irq_irrecv             (ibase+14)      /* IR Receiver Interrupt */
+#define irq_host_int1          (ibase+13)      /* Host-to-Host Interrupt 1 */
+#define irq_host_int0          (ibase+12)      /* Host-to-Host Interrupt 0 */
+#define irq_qpsk_hecerr                (ibase+11)      /* QPSK HEC Error Interrupt */
+#define irq_qpsk_crcerr                (ibase+10)      /* QPSK AAL-5 CRC Error
+                                                * Interrupt */
+/* 9 unused    (bit 09) */
+/* 8 unused    (bit 08) */
+#define irq_psicrcerr          (ibase+7)       /* QAM PSI CRC Error
+                                                * Interrupt */
+#define irq_psilength_err      (ibase+6)       /* QAM PSI Length Error
+                                                * Interrupt */
+#define irq_esfforward         (ibase+5)       /* ESF Interrupt Mark From
+                                                * Forward Path Reference -
+                                                * every 3ms when forward Mbits
+                                                * and forward slot control
+                                                * bytes are updated. */
+#define irq_esfreverse         (ibase+4)       /* ESF Interrupt Mark from
+                                                * Reverse Path Reference -
+                                                * delayed from forward mark by
+                                                * the ranging delay plus a
+                                                * fixed amount. When reverse
+                                                * Mbits and reverse slot
+                                                * control bytes are updated.
+                                                * Occurs every 3ms for 3.0M and
+                                                * 1.554 M upstream rates and
+                                                * every 6 ms for 256K upstream
+                                                * rate. */
+#define irq_aloha_timeout      (ibase+3)       /* Slotted-Aloha timeout on
+                                                * Channel 1. */
+#define irq_reservation                (ibase+2)       /* Partial (or Incremental)
+                                                * Reservation Message Completed
+                                                * or Slotted aloha verify for
+                                                * channel 1. */
+#define irq_aloha3             (ibase+1)       /* Slotted-Aloha Message Verify
+                                                * Interrupt or Reservation
+                                                * increment completed for
+                                                * channel 3. */
+#define irq_mpeg_d             (ibase+0)       /* MPEG Decoder Interrupt */
+#endif /* _ASM_MACH_POWERTV_INTERRUPTS_H_ */
+
diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h
new file mode 100644 (file)
index 0000000..e6276d5
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *     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.
+ *
+ * Portions Copyright (C)  Cisco Systems, Inc.
+ */
+#ifndef __ASM_MACH_POWERTV_IOREMAP_H
+#define __ASM_MACH_POWERTV_IOREMAP_H
+
+#include <linux/types.h>
+
+#define LOW_MEM_BOUNDARY_PHYS  0x20000000
+#define LOW_MEM_BOUNDARY_MASK  (~(LOW_MEM_BOUNDARY_PHYS - 1))
+
+/*
+ * The bus addresses are different than the physical addresses that
+ * the processor sees by an offset. This offset varies by ASIC
+ * version. Define a variable to hold the offset and some macros to
+ * make the conversion simpler. */
+extern unsigned long phys_to_bus_offset;
+
+#ifdef CONFIG_HIGHMEM
+#define MEM_GAP_PHYS           0x60000000
+/*
+ * TODO: We will use the hard code for conversion between physical and
+ * bus until the bootloader releases their device tree to us.
+ */
+#define phys_to_bus(x) (((x) < LOW_MEM_BOUNDARY_PHYS) ? \
+       ((x) + phys_to_bus_offset) : (x))
+#define bus_to_phys(x) (((x) < MEM_GAP_PHYS_ADDR) ? \
+       ((x) - phys_to_bus_offset) : (x))
+#else
+#define phys_to_bus(x) ((x) + phys_to_bus_offset)
+#define bus_to_phys(x) ((x) - phys_to_bus_offset)
+#endif
+
+/*
+ * Determine whether the address we are given is for an ASIC device
+ * Params:  addr    Address to check
+ * Returns: Zero if the address is not for ASIC devices, non-zero
+ *      if it is.
+ */
+static inline int asic_is_device_addr(phys_t addr)
+{
+       return !((phys_t)addr & (phys_t) LOW_MEM_BOUNDARY_MASK);
+}
+
+/*
+ * Determine whether the address we are given is external RAM mappable
+ * into KSEG1.
+ * Params:  addr    Address to check
+ * Returns: Zero if the address is not for external RAM and
+ */
+static inline int asic_is_lowmem_ram_addr(phys_t addr)
+{
+       /*
+        * The RAM always starts at the following address in the processor's
+        * physical address space
+        */
+       static const phys_t phys_ram_base = 0x10000000;
+       phys_t bus_ram_base;
+
+       bus_ram_base = phys_to_bus_offset + phys_ram_base;
+
+       return addr >= bus_ram_base &&
+               addr < (bus_ram_base + (LOW_MEM_BOUNDARY_PHYS - phys_ram_base));
+}
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+       return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+       unsigned long flags)
+{
+       return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+       return 0;
+}
+#endif /* __ASM_MACH_POWERTV_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-powertv/irq.h b/arch/mips/include/asm/mach-powertv/irq.h
new file mode 100644 (file)
index 0000000..4bd5d0c
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+
+#ifndef _ASM_MACH_POWERTV_IRQ_H
+#define _ASM_MACH_POWERTV_IRQ_H
+#include <asm/mach-powertv/interrupts.h>
+
+#define MIPS_CPU_IRQ_BASE      ibase
+#define NR_IRQS                        127
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-clock.h b/arch/mips/include/asm/mach-powertv/powertv-clock.h
new file mode 100644 (file)
index 0000000..6f3e9a0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+/*
+ * Local definitions for the powertv PCI code
+ */
+
+#ifndef _POWERTV_PCI_POWERTV_PCI_H_
+#define _POWERTV_PCI_POWERTV_PCI_H_
+extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+extern int asic_pcie_init(void);
+extern int asic_pcie_init(void);
+
+extern int log_level;
+#endif
similarity index 56%
rename from arch/mips/include/asm/mach-excite/war.h
rename to arch/mips/include/asm/mach-powertv/war.h
index 1f82180..7ac05ec 100644 (file)
@@ -3,10 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
+ * This version for the PowerTV platform copied from the Malta version.
+ *
  * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
  */
-#ifndef __ASM_MIPS_MACH_EXCITE_WAR_H
-#define __ASM_MIPS_MACH_EXCITE_WAR_H
+#ifndef __ASM_MACH_POWERTV_WAR_H
+#define __ASM_MACH_POWERTV_WAR_H
 
 #define R4600_V1_INDEX_ICACHEOP_WAR    0
 #define R4600_V1_HIT_CACHEOP_WAR       0
 #define R5432_CP0_INTERRUPT_WAR                0
 #define BCM1250_M3_WAR                 0
 #define SIBYTE_1956_WAR                        0
-#define MIPS4K_ICACHE_REFILL_WAR       0
-#define MIPS_CACHE_SYNC_WAR            0
+#define MIPS4K_ICACHE_REFILL_WAR       1
+#define MIPS_CACHE_SYNC_WAR            1
 #define TX49XX_ICACHE_INDEX_INV_WAR    0
-#define RM9000_CDEX_SMP_WAR            1
-#define ICACHE_REFILLS_WORKAROUND_WAR   1
+#define RM9000_CDEX_SMP_WAR            0
+#define ICACHE_REFILLS_WORKAROUND_WAR  1
 #define R10000_LLSC_WAR                        0
-#define MIPS34K_MISSED_ITLB_WAR        0
+#define MIPS34K_MISSED_ITLB_WAR                0
 
-#endif /* __ASM_MIPS_MACH_EXCITE_WAR_H */
+#endif /* __ASM_MACH_POWERTV_WAR_H */
index a576ce0..d14e2ad 100644 (file)
 /* offsets from base register */
 #define BONITO(x)      (x)
 
-#elif defined(CONFIG_LEMOTE_FULOONG2E)
-
-#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
-#define BONITO_IRQ_BASE   32
-
 #else
 
 /*
index 6083db5..145bb81 100644 (file)
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+
+#define TLBMISS_HANDLER_SETUP_PGD(pgd)                         \
+       tlbmiss_handler_setup_pgd((unsigned long)(pgd))
+
+static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
+{
+       /* Check for swapper_pg_dir and convert to physical address. */
+       if ((pgd & CKSEG3) == CKSEG0)
+               pgd = CPHYSADDR(pgd);
+       write_c0_context(pgd << 11);
+}
+
+#define TLBMISS_HANDLER_SETUP()                                                \
+       do {                                                            \
+               TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);              \
+               write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+       } while (0)
+
+
+static inline unsigned long get_current_pgd(void)
+{
+       return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
+}
+
+#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
+
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
  * to the current pgd for each processor. Also, the proc. id is stuffed
@@ -46,7 +73,7 @@ extern unsigned long pgd_current[];
        back_to_back_c0_hazard();                                       \
        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
-
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
 #define ASID_INC       0x40
diff --git a/arch/mips/include/asm/octeon/cvmx-agl-defs.h b/arch/mips/include/asm/octeon/cvmx-agl-defs.h
new file mode 100644 (file)
index 0000000..ec94b9a
--- /dev/null
@@ -0,0 +1,1194 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_AGL_DEFS_H__
+#define __CVMX_AGL_DEFS_H__
+
+#define CVMX_AGL_GMX_BAD_REG \
+        CVMX_ADD_IO_SEG(0x00011800E0000518ull)
+#define CVMX_AGL_GMX_BIST \
+        CVMX_ADD_IO_SEG(0x00011800E0000400ull)
+#define CVMX_AGL_GMX_DRV_CTL \
+        CVMX_ADD_IO_SEG(0x00011800E00007F0ull)
+#define CVMX_AGL_GMX_INF_MODE \
+        CVMX_ADD_IO_SEG(0x00011800E00007F8ull)
+#define CVMX_AGL_GMX_PRTX_CFG(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000010ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM0(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000180ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM1(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000188ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM2(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000190ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM3(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000198ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM4(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00001A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM5(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00001A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM_EN(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000108ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000100ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_DECISION(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000040ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_CHK(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000020ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000018ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_MAX(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000030ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_MIN(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000028ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_IFG(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000058ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_INT_EN(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000008ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_INT_REG(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000000ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_JABBER(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000038ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_PAUSE_DROP_TIME(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000068ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000050ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000088ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000098ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DMAC(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00000A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DRP(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00000B8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000080ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00000C0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000090ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DMAC(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00000A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00000B0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_UDD_SKP(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000048ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RX_BP_DROPX(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000420ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_BP_OFFX(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000460ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_BP_ONX(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000440ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_PRT_INFO \
+        CVMX_ADD_IO_SEG(0x00011800E00004E8ull)
+#define CVMX_AGL_GMX_RX_TX_STATUS \
+        CVMX_ADD_IO_SEG(0x00011800E00007E8ull)
+#define CVMX_AGL_GMX_SMACX(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000230ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_STAT_BP \
+        CVMX_ADD_IO_SEG(0x00011800E0000520ull)
+#define CVMX_AGL_GMX_TXX_APPEND(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000218ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000270ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_MIN_PKT(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000240ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_INTERVAL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000248ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_TIME(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000238ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_TOGO(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000258ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_ZERO(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000260ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_SOFT_PAUSE(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000250ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT0(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000280ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT1(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000288ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT2(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000290ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT3(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000298ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT4(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT5(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT6(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002B0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT7(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002B8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT8(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002C0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT9(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E00002C8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STATS_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000268ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_THRESH(offset) \
+        CVMX_ADD_IO_SEG(0x00011800E0000210ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TX_BP \
+        CVMX_ADD_IO_SEG(0x00011800E00004D0ull)
+#define CVMX_AGL_GMX_TX_COL_ATTEMPT \
+        CVMX_ADD_IO_SEG(0x00011800E0000498ull)
+#define CVMX_AGL_GMX_TX_IFG \
+        CVMX_ADD_IO_SEG(0x00011800E0000488ull)
+#define CVMX_AGL_GMX_TX_INT_EN \
+        CVMX_ADD_IO_SEG(0x00011800E0000508ull)
+#define CVMX_AGL_GMX_TX_INT_REG \
+        CVMX_ADD_IO_SEG(0x00011800E0000500ull)
+#define CVMX_AGL_GMX_TX_JAM \
+        CVMX_ADD_IO_SEG(0x00011800E0000490ull)
+#define CVMX_AGL_GMX_TX_LFSR \
+        CVMX_ADD_IO_SEG(0x00011800E00004F8ull)
+#define CVMX_AGL_GMX_TX_OVR_BP \
+        CVMX_ADD_IO_SEG(0x00011800E00004C8ull)
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC \
+        CVMX_ADD_IO_SEG(0x00011800E00004A0ull)
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE \
+        CVMX_ADD_IO_SEG(0x00011800E00004A8ull)
+
+union cvmx_agl_gmx_bad_reg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_bad_reg_s {
+               uint64_t reserved_38_63:26;
+               uint64_t txpsh1:1;
+               uint64_t txpop1:1;
+               uint64_t ovrflw1:1;
+               uint64_t txpsh:1;
+               uint64_t txpop:1;
+               uint64_t ovrflw:1;
+               uint64_t reserved_27_31:5;
+               uint64_t statovr:1;
+               uint64_t reserved_23_25:3;
+               uint64_t loststat:1;
+               uint64_t reserved_4_21:18;
+               uint64_t out_ovr:2;
+               uint64_t reserved_0_1:2;
+       } s;
+       struct cvmx_agl_gmx_bad_reg_s cn52xx;
+       struct cvmx_agl_gmx_bad_reg_s cn52xxp1;
+       struct cvmx_agl_gmx_bad_reg_cn56xx {
+               uint64_t reserved_35_63:29;
+               uint64_t txpsh:1;
+               uint64_t txpop:1;
+               uint64_t ovrflw:1;
+               uint64_t reserved_27_31:5;
+               uint64_t statovr:1;
+               uint64_t reserved_23_25:3;
+               uint64_t loststat:1;
+               uint64_t reserved_3_21:19;
+               uint64_t out_ovr:1;
+               uint64_t reserved_0_1:2;
+       } cn56xx;
+       struct cvmx_agl_gmx_bad_reg_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_bist {
+       uint64_t u64;
+       struct cvmx_agl_gmx_bist_s {
+               uint64_t reserved_10_63:54;
+               uint64_t status:10;
+       } s;
+       struct cvmx_agl_gmx_bist_s cn52xx;
+       struct cvmx_agl_gmx_bist_s cn52xxp1;
+       struct cvmx_agl_gmx_bist_s cn56xx;
+       struct cvmx_agl_gmx_bist_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_drv_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_drv_ctl_s {
+               uint64_t reserved_49_63:15;
+               uint64_t byp_en1:1;
+               uint64_t reserved_45_47:3;
+               uint64_t pctl1:5;
+               uint64_t reserved_37_39:3;
+               uint64_t nctl1:5;
+               uint64_t reserved_17_31:15;
+               uint64_t byp_en:1;
+               uint64_t reserved_13_15:3;
+               uint64_t pctl:5;
+               uint64_t reserved_5_7:3;
+               uint64_t nctl:5;
+       } s;
+       struct cvmx_agl_gmx_drv_ctl_s cn52xx;
+       struct cvmx_agl_gmx_drv_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_drv_ctl_cn56xx {
+               uint64_t reserved_17_63:47;
+               uint64_t byp_en:1;
+               uint64_t reserved_13_15:3;
+               uint64_t pctl:5;
+               uint64_t reserved_5_7:3;
+               uint64_t nctl:5;
+       } cn56xx;
+       struct cvmx_agl_gmx_drv_ctl_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_inf_mode {
+       uint64_t u64;
+       struct cvmx_agl_gmx_inf_mode_s {
+               uint64_t reserved_2_63:62;
+               uint64_t en:1;
+               uint64_t reserved_0_0:1;
+       } s;
+       struct cvmx_agl_gmx_inf_mode_s cn52xx;
+       struct cvmx_agl_gmx_inf_mode_s cn52xxp1;
+       struct cvmx_agl_gmx_inf_mode_s cn56xx;
+       struct cvmx_agl_gmx_inf_mode_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_prtx_cfg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_prtx_cfg_s {
+               uint64_t reserved_6_63:58;
+               uint64_t tx_en:1;
+               uint64_t rx_en:1;
+               uint64_t slottime:1;
+               uint64_t duplex:1;
+               uint64_t speed:1;
+               uint64_t en:1;
+       } s;
+       struct cvmx_agl_gmx_prtx_cfg_s cn52xx;
+       struct cvmx_agl_gmx_prtx_cfg_s cn52xxp1;
+       struct cvmx_agl_gmx_prtx_cfg_s cn56xx;
+       struct cvmx_agl_gmx_prtx_cfg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam0 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam0_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam1 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam1_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam2 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam2_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam3 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam3_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam4 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam4_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam5 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam5_s {
+               uint64_t adr:64;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam_en {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_cam_en_s {
+               uint64_t reserved_8_63:56;
+               uint64_t en:8;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_adr_ctl_s {
+               uint64_t reserved_4_63:60;
+               uint64_t cam_mode:1;
+               uint64_t mcst:2;
+               uint64_t bcst:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xx;
+       struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xx;
+       struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_decision {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_decision_s {
+               uint64_t reserved_5_63:59;
+               uint64_t cnt:5;
+       } s;
+       struct cvmx_agl_gmx_rxx_decision_s cn52xx;
+       struct cvmx_agl_gmx_rxx_decision_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_decision_s cn56xx;
+       struct cvmx_agl_gmx_rxx_decision_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_chk {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_frm_chk_s {
+               uint64_t reserved_9_63:55;
+               uint64_t skperr:1;
+               uint64_t rcverr:1;
+               uint64_t lenerr:1;
+               uint64_t alnerr:1;
+               uint64_t fcserr:1;
+               uint64_t jabber:1;
+               uint64_t maxerr:1;
+               uint64_t reserved_1_1:1;
+               uint64_t minerr:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_frm_chk_s cn52xx;
+       struct cvmx_agl_gmx_rxx_frm_chk_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_frm_chk_s cn56xx;
+       struct cvmx_agl_gmx_rxx_frm_chk_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_frm_ctl_s {
+               uint64_t reserved_10_63:54;
+               uint64_t pre_align:1;
+               uint64_t pad_len:1;
+               uint64_t vlan_len:1;
+               uint64_t pre_free:1;
+               uint64_t ctl_smac:1;
+               uint64_t ctl_mcst:1;
+               uint64_t ctl_bck:1;
+               uint64_t ctl_drp:1;
+               uint64_t pre_strp:1;
+               uint64_t pre_chk:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xx;
+       struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xx;
+       struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_max {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_frm_max_s {
+               uint64_t reserved_16_63:48;
+               uint64_t len:16;
+       } s;
+       struct cvmx_agl_gmx_rxx_frm_max_s cn52xx;
+       struct cvmx_agl_gmx_rxx_frm_max_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_frm_max_s cn56xx;
+       struct cvmx_agl_gmx_rxx_frm_max_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_min {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_frm_min_s {
+               uint64_t reserved_16_63:48;
+               uint64_t len:16;
+       } s;
+       struct cvmx_agl_gmx_rxx_frm_min_s cn52xx;
+       struct cvmx_agl_gmx_rxx_frm_min_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_frm_min_s cn56xx;
+       struct cvmx_agl_gmx_rxx_frm_min_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_ifg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_ifg_s {
+               uint64_t reserved_4_63:60;
+               uint64_t ifg:4;
+       } s;
+       struct cvmx_agl_gmx_rxx_ifg_s cn52xx;
+       struct cvmx_agl_gmx_rxx_ifg_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_ifg_s cn56xx;
+       struct cvmx_agl_gmx_rxx_ifg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_int_en {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_int_en_s {
+               uint64_t reserved_20_63:44;
+               uint64_t pause_drp:1;
+               uint64_t reserved_16_18:3;
+               uint64_t ifgerr:1;
+               uint64_t coldet:1;
+               uint64_t falerr:1;
+               uint64_t rsverr:1;
+               uint64_t pcterr:1;
+               uint64_t ovrerr:1;
+               uint64_t reserved_9_9:1;
+               uint64_t skperr:1;
+               uint64_t rcverr:1;
+               uint64_t lenerr:1;
+               uint64_t alnerr:1;
+               uint64_t fcserr:1;
+               uint64_t jabber:1;
+               uint64_t maxerr:1;
+               uint64_t reserved_1_1:1;
+               uint64_t minerr:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_int_en_s cn52xx;
+       struct cvmx_agl_gmx_rxx_int_en_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_int_en_s cn56xx;
+       struct cvmx_agl_gmx_rxx_int_en_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_int_reg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_int_reg_s {
+               uint64_t reserved_20_63:44;
+               uint64_t pause_drp:1;
+               uint64_t reserved_16_18:3;
+               uint64_t ifgerr:1;
+               uint64_t coldet:1;
+               uint64_t falerr:1;
+               uint64_t rsverr:1;
+               uint64_t pcterr:1;
+               uint64_t ovrerr:1;
+               uint64_t reserved_9_9:1;
+               uint64_t skperr:1;
+               uint64_t rcverr:1;
+               uint64_t lenerr:1;
+               uint64_t alnerr:1;
+               uint64_t fcserr:1;
+               uint64_t jabber:1;
+               uint64_t maxerr:1;
+               uint64_t reserved_1_1:1;
+               uint64_t minerr:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_int_reg_s cn52xx;
+       struct cvmx_agl_gmx_rxx_int_reg_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_int_reg_s cn56xx;
+       struct cvmx_agl_gmx_rxx_int_reg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_jabber {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_jabber_s {
+               uint64_t reserved_16_63:48;
+               uint64_t cnt:16;
+       } s;
+       struct cvmx_agl_gmx_rxx_jabber_s cn52xx;
+       struct cvmx_agl_gmx_rxx_jabber_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_jabber_s cn56xx;
+       struct cvmx_agl_gmx_rxx_jabber_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_pause_drop_time {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_pause_drop_time_s {
+               uint64_t reserved_16_63:48;
+               uint64_t status:16;
+       } s;
+       struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xx;
+       struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xx;
+       struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_ctl_s {
+               uint64_t reserved_1_63:63;
+               uint64_t rd_clr:1;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_octs_s {
+               uint64_t reserved_48_63:16;
+               uint64_t cnt:48;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_octs_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_octs_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_octs_ctl_s {
+               uint64_t reserved_48_63:16;
+               uint64_t cnt:48;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_dmac {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_octs_dmac_s {
+               uint64_t reserved_48_63:16;
+               uint64_t cnt:48;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_drp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_octs_drp_s {
+               uint64_t reserved_48_63:16;
+               uint64_t cnt:48;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_pkts_s {
+               uint64_t reserved_32_63:32;
+               uint64_t cnt:32;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_bad {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_pkts_bad_s {
+               uint64_t reserved_32_63:32;
+               uint64_t cnt:32;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s {
+               uint64_t reserved_32_63:32;
+               uint64_t cnt:32;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_dmac {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s {
+               uint64_t reserved_32_63:32;
+               uint64_t cnt:32;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_drp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_stats_pkts_drp_s {
+               uint64_t reserved_32_63:32;
+               uint64_t cnt:32;
+       } s;
+       struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xx;
+       struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_udd_skp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rxx_udd_skp_s {
+               uint64_t reserved_9_63:55;
+               uint64_t fcssel:1;
+               uint64_t reserved_7_7:1;
+               uint64_t len:7;
+       } s;
+       struct cvmx_agl_gmx_rxx_udd_skp_s cn52xx;
+       struct cvmx_agl_gmx_rxx_udd_skp_s cn52xxp1;
+       struct cvmx_agl_gmx_rxx_udd_skp_s cn56xx;
+       struct cvmx_agl_gmx_rxx_udd_skp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_dropx {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rx_bp_dropx_s {
+               uint64_t reserved_6_63:58;
+               uint64_t mark:6;
+       } s;
+       struct cvmx_agl_gmx_rx_bp_dropx_s cn52xx;
+       struct cvmx_agl_gmx_rx_bp_dropx_s cn52xxp1;
+       struct cvmx_agl_gmx_rx_bp_dropx_s cn56xx;
+       struct cvmx_agl_gmx_rx_bp_dropx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_offx {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rx_bp_offx_s {
+               uint64_t reserved_6_63:58;
+               uint64_t mark:6;
+       } s;
+       struct cvmx_agl_gmx_rx_bp_offx_s cn52xx;
+       struct cvmx_agl_gmx_rx_bp_offx_s cn52xxp1;
+       struct cvmx_agl_gmx_rx_bp_offx_s cn56xx;
+       struct cvmx_agl_gmx_rx_bp_offx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_onx {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rx_bp_onx_s {
+               uint64_t reserved_9_63:55;
+               uint64_t mark:9;
+       } s;
+       struct cvmx_agl_gmx_rx_bp_onx_s cn52xx;
+       struct cvmx_agl_gmx_rx_bp_onx_s cn52xxp1;
+       struct cvmx_agl_gmx_rx_bp_onx_s cn56xx;
+       struct cvmx_agl_gmx_rx_bp_onx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_prt_info {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rx_prt_info_s {
+               uint64_t reserved_18_63:46;
+               uint64_t drop:2;
+               uint64_t reserved_2_15:14;
+               uint64_t commit:2;
+       } s;
+       struct cvmx_agl_gmx_rx_prt_info_s cn52xx;
+       struct cvmx_agl_gmx_rx_prt_info_s cn52xxp1;
+       struct cvmx_agl_gmx_rx_prt_info_cn56xx {
+               uint64_t reserved_17_63:47;
+               uint64_t drop:1;
+               uint64_t reserved_1_15:15;
+               uint64_t commit:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_rx_prt_info_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_tx_status {
+       uint64_t u64;
+       struct cvmx_agl_gmx_rx_tx_status_s {
+               uint64_t reserved_6_63:58;
+               uint64_t tx:2;
+               uint64_t reserved_2_3:2;
+               uint64_t rx:2;
+       } s;
+       struct cvmx_agl_gmx_rx_tx_status_s cn52xx;
+       struct cvmx_agl_gmx_rx_tx_status_s cn52xxp1;
+       struct cvmx_agl_gmx_rx_tx_status_cn56xx {
+               uint64_t reserved_5_63:59;
+               uint64_t tx:1;
+               uint64_t reserved_1_3:3;
+               uint64_t rx:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_rx_tx_status_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_smacx {
+       uint64_t u64;
+       struct cvmx_agl_gmx_smacx_s {
+               uint64_t reserved_48_63:16;
+               uint64_t smac:48;
+       } s;
+       struct cvmx_agl_gmx_smacx_s cn52xx;
+       struct cvmx_agl_gmx_smacx_s cn52xxp1;
+       struct cvmx_agl_gmx_smacx_s cn56xx;
+       struct cvmx_agl_gmx_smacx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_stat_bp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_stat_bp_s {
+               uint64_t reserved_17_63:47;
+               uint64_t bp:1;
+               uint64_t cnt:16;
+       } s;
+       struct cvmx_agl_gmx_stat_bp_s cn52xx;
+       struct cvmx_agl_gmx_stat_bp_s cn52xxp1;
+       struct cvmx_agl_gmx_stat_bp_s cn56xx;
+       struct cvmx_agl_gmx_stat_bp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_append {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_append_s {
+               uint64_t reserved_4_63:60;
+               uint64_t force_fcs:1;
+               uint64_t fcs:1;
+               uint64_t pad:1;
+               uint64_t preamble:1;
+       } s;
+       struct cvmx_agl_gmx_txx_append_s cn52xx;
+       struct cvmx_agl_gmx_txx_append_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_append_s cn56xx;
+       struct cvmx_agl_gmx_txx_append_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_ctl_s {
+               uint64_t reserved_2_63:62;
+               uint64_t xsdef_en:1;
+               uint64_t xscol_en:1;
+       } s;
+       struct cvmx_agl_gmx_txx_ctl_s cn52xx;
+       struct cvmx_agl_gmx_txx_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_ctl_s cn56xx;
+       struct cvmx_agl_gmx_txx_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_min_pkt {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_min_pkt_s {
+               uint64_t reserved_8_63:56;
+               uint64_t min_size:8;
+       } s;
+       struct cvmx_agl_gmx_txx_min_pkt_s cn52xx;
+       struct cvmx_agl_gmx_txx_min_pkt_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_min_pkt_s cn56xx;
+       struct cvmx_agl_gmx_txx_min_pkt_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_pkt_interval {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_pause_pkt_interval_s {
+               uint64_t reserved_16_63:48;
+               uint64_t interval:16;
+       } s;
+       struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xx;
+       struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xx;
+       struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_pkt_time {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_pause_pkt_time_s {
+               uint64_t reserved_16_63:48;
+               uint64_t time:16;
+       } s;
+       struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xx;
+       struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xx;
+       struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_togo {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_pause_togo_s {
+               uint64_t reserved_16_63:48;
+               uint64_t time:16;
+       } s;
+       struct cvmx_agl_gmx_txx_pause_togo_s cn52xx;
+       struct cvmx_agl_gmx_txx_pause_togo_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_pause_togo_s cn56xx;
+       struct cvmx_agl_gmx_txx_pause_togo_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_zero {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_pause_zero_s {
+               uint64_t reserved_1_63:63;
+               uint64_t send:1;
+       } s;
+       struct cvmx_agl_gmx_txx_pause_zero_s cn52xx;
+       struct cvmx_agl_gmx_txx_pause_zero_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_pause_zero_s cn56xx;
+       struct cvmx_agl_gmx_txx_pause_zero_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_soft_pause {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_soft_pause_s {
+               uint64_t reserved_16_63:48;
+               uint64_t time:16;
+       } s;
+       struct cvmx_agl_gmx_txx_soft_pause_s cn52xx;
+       struct cvmx_agl_gmx_txx_soft_pause_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_soft_pause_s cn56xx;
+       struct cvmx_agl_gmx_txx_soft_pause_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat0 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat0_s {
+               uint64_t xsdef:32;
+               uint64_t xscol:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat0_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat0_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat0_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat0_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat1 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat1_s {
+               uint64_t scol:32;
+               uint64_t mcol:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat1_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat1_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat1_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat1_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat2 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat2_s {
+               uint64_t reserved_48_63:16;
+               uint64_t octs:48;
+       } s;
+       struct cvmx_agl_gmx_txx_stat2_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat2_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat2_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat2_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat3 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat3_s {
+               uint64_t reserved_32_63:32;
+               uint64_t pkts:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat3_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat3_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat3_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat3_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat4 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat4_s {
+               uint64_t hist1:32;
+               uint64_t hist0:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat4_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat4_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat4_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat4_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat5 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat5_s {
+               uint64_t hist3:32;
+               uint64_t hist2:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat5_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat5_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat5_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat5_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat6 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat6_s {
+               uint64_t hist5:32;
+               uint64_t hist4:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat6_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat6_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat6_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat6_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat7 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat7_s {
+               uint64_t hist7:32;
+               uint64_t hist6:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat7_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat7_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat7_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat7_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat8 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat8_s {
+               uint64_t mcst:32;
+               uint64_t bcst:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat8_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat8_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat8_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat8_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat9 {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stat9_s {
+               uint64_t undflw:32;
+               uint64_t ctl:32;
+       } s;
+       struct cvmx_agl_gmx_txx_stat9_s cn52xx;
+       struct cvmx_agl_gmx_txx_stat9_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stat9_s cn56xx;
+       struct cvmx_agl_gmx_txx_stat9_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stats_ctl {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_stats_ctl_s {
+               uint64_t reserved_1_63:63;
+               uint64_t rd_clr:1;
+       } s;
+       struct cvmx_agl_gmx_txx_stats_ctl_s cn52xx;
+       struct cvmx_agl_gmx_txx_stats_ctl_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_stats_ctl_s cn56xx;
+       struct cvmx_agl_gmx_txx_stats_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_thresh {
+       uint64_t u64;
+       struct cvmx_agl_gmx_txx_thresh_s {
+               uint64_t reserved_6_63:58;
+               uint64_t cnt:6;
+       } s;
+       struct cvmx_agl_gmx_txx_thresh_s cn52xx;
+       struct cvmx_agl_gmx_txx_thresh_s cn52xxp1;
+       struct cvmx_agl_gmx_txx_thresh_s cn56xx;
+       struct cvmx_agl_gmx_txx_thresh_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_bp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_bp_s {
+               uint64_t reserved_2_63:62;
+               uint64_t bp:2;
+       } s;
+       struct cvmx_agl_gmx_tx_bp_s cn52xx;
+       struct cvmx_agl_gmx_tx_bp_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_bp_cn56xx {
+               uint64_t reserved_1_63:63;
+               uint64_t bp:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_tx_bp_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_col_attempt {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_col_attempt_s {
+               uint64_t reserved_5_63:59;
+               uint64_t limit:5;
+       } s;
+       struct cvmx_agl_gmx_tx_col_attempt_s cn52xx;
+       struct cvmx_agl_gmx_tx_col_attempt_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_col_attempt_s cn56xx;
+       struct cvmx_agl_gmx_tx_col_attempt_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_ifg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_ifg_s {
+               uint64_t reserved_8_63:56;
+               uint64_t ifg2:4;
+               uint64_t ifg1:4;
+       } s;
+       struct cvmx_agl_gmx_tx_ifg_s cn52xx;
+       struct cvmx_agl_gmx_tx_ifg_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_ifg_s cn56xx;
+       struct cvmx_agl_gmx_tx_ifg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_int_en {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_int_en_s {
+               uint64_t reserved_18_63:46;
+               uint64_t late_col:2;
+               uint64_t reserved_14_15:2;
+               uint64_t xsdef:2;
+               uint64_t reserved_10_11:2;
+               uint64_t xscol:2;
+               uint64_t reserved_4_7:4;
+               uint64_t undflw:2;
+               uint64_t reserved_1_1:1;
+               uint64_t pko_nxa:1;
+       } s;
+       struct cvmx_agl_gmx_tx_int_en_s cn52xx;
+       struct cvmx_agl_gmx_tx_int_en_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_int_en_cn56xx {
+               uint64_t reserved_17_63:47;
+               uint64_t late_col:1;
+               uint64_t reserved_13_15:3;
+               uint64_t xsdef:1;
+               uint64_t reserved_9_11:3;
+               uint64_t xscol:1;
+               uint64_t reserved_3_7:5;
+               uint64_t undflw:1;
+               uint64_t reserved_1_1:1;
+               uint64_t pko_nxa:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_tx_int_en_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_int_reg {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_int_reg_s {
+               uint64_t reserved_18_63:46;
+               uint64_t late_col:2;
+               uint64_t reserved_14_15:2;
+               uint64_t xsdef:2;
+               uint64_t reserved_10_11:2;
+               uint64_t xscol:2;
+               uint64_t reserved_4_7:4;
+               uint64_t undflw:2;
+               uint64_t reserved_1_1:1;
+               uint64_t pko_nxa:1;
+       } s;
+       struct cvmx_agl_gmx_tx_int_reg_s cn52xx;
+       struct cvmx_agl_gmx_tx_int_reg_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_int_reg_cn56xx {
+               uint64_t reserved_17_63:47;
+               uint64_t late_col:1;
+               uint64_t reserved_13_15:3;
+               uint64_t xsdef:1;
+               uint64_t reserved_9_11:3;
+               uint64_t xscol:1;
+               uint64_t reserved_3_7:5;
+               uint64_t undflw:1;
+               uint64_t reserved_1_1:1;
+               uint64_t pko_nxa:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_tx_int_reg_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_jam {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_jam_s {
+               uint64_t reserved_8_63:56;
+               uint64_t jam:8;
+       } s;
+       struct cvmx_agl_gmx_tx_jam_s cn52xx;
+       struct cvmx_agl_gmx_tx_jam_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_jam_s cn56xx;
+       struct cvmx_agl_gmx_tx_jam_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_lfsr {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_lfsr_s {
+               uint64_t reserved_16_63:48;
+               uint64_t lfsr:16;
+       } s;
+       struct cvmx_agl_gmx_tx_lfsr_s cn52xx;
+       struct cvmx_agl_gmx_tx_lfsr_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_lfsr_s cn56xx;
+       struct cvmx_agl_gmx_tx_lfsr_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_ovr_bp {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_ovr_bp_s {
+               uint64_t reserved_10_63:54;
+               uint64_t en:2;
+               uint64_t reserved_6_7:2;
+               uint64_t bp:2;
+               uint64_t reserved_2_3:2;
+               uint64_t ign_full:2;
+       } s;
+       struct cvmx_agl_gmx_tx_ovr_bp_s cn52xx;
+       struct cvmx_agl_gmx_tx_ovr_bp_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_ovr_bp_cn56xx {
+               uint64_t reserved_9_63:55;
+               uint64_t en:1;
+               uint64_t reserved_5_7:3;
+               uint64_t bp:1;
+               uint64_t reserved_1_3:3;
+               uint64_t ign_full:1;
+       } cn56xx;
+       struct cvmx_agl_gmx_tx_ovr_bp_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_pause_pkt_dmac {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_pause_pkt_dmac_s {
+               uint64_t reserved_48_63:16;
+               uint64_t dmac:48;
+       } s;
+       struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xx;
+       struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xx;
+       struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_pause_pkt_type {
+       uint64_t u64;
+       struct cvmx_agl_gmx_tx_pause_pkt_type_s {
+               uint64_t reserved_16_63:48;
+               uint64_t type:16;
+       } s;
+       struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xx;
+       struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xxp1;
+       struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xx;
+       struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-mixx-defs.h b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h
new file mode 100644 (file)
index 0000000..dab6dca
--- /dev/null
@@ -0,0 +1,248 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_MIXX_DEFS_H__
+#define __CVMX_MIXX_DEFS_H__
+
+#define CVMX_MIXX_BIST(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100078ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_CTL(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100020ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_INTENA(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100050ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRCNT(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100030ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRHWM(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100028ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRING1(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100010ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRING2(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100018ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ISR(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100048ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORCNT(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100040ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORHWM(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100038ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORING1(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100000ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORING2(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100008ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_REMCNT(offset) \
+        CVMX_ADD_IO_SEG(0x0001070000100058ull + (((offset) & 1) * 2048))
+
+union cvmx_mixx_bist {
+       uint64_t u64;
+       struct cvmx_mixx_bist_s {
+               uint64_t reserved_4_63:60;
+               uint64_t mrqdat:1;
+               uint64_t ipfdat:1;
+               uint64_t irfdat:1;
+               uint64_t orfdat:1;
+       } s;
+       struct cvmx_mixx_bist_s cn52xx;
+       struct cvmx_mixx_bist_s cn52xxp1;
+       struct cvmx_mixx_bist_s cn56xx;
+       struct cvmx_mixx_bist_s cn56xxp1;
+};
+
+union cvmx_mixx_ctl {
+       uint64_t u64;
+       struct cvmx_mixx_ctl_s {
+               uint64_t reserved_8_63:56;
+               uint64_t crc_strip:1;
+               uint64_t busy:1;
+               uint64_t en:1;
+               uint64_t reset:1;
+               uint64_t lendian:1;
+               uint64_t nbtarb:1;
+               uint64_t mrq_hwm:2;
+       } s;
+       struct cvmx_mixx_ctl_s cn52xx;
+       struct cvmx_mixx_ctl_s cn52xxp1;
+       struct cvmx_mixx_ctl_s cn56xx;
+       struct cvmx_mixx_ctl_s cn56xxp1;
+};
+
+union cvmx_mixx_intena {
+       uint64_t u64;
+       struct cvmx_mixx_intena_s {
+               uint64_t reserved_7_63:57;
+               uint64_t orunena:1;
+               uint64_t irunena:1;
+               uint64_t data_drpena:1;
+               uint64_t ithena:1;
+               uint64_t othena:1;
+               uint64_t ivfena:1;
+               uint64_t ovfena:1;
+       } s;
+       struct cvmx_mixx_intena_s cn52xx;
+       struct cvmx_mixx_intena_s cn52xxp1;
+       struct cvmx_mixx_intena_s cn56xx;
+       struct cvmx_mixx_intena_s cn56xxp1;
+};
+
+union cvmx_mixx_ircnt {
+       uint64_t u64;
+       struct cvmx_mixx_ircnt_s {
+               uint64_t reserved_20_63:44;
+               uint64_t ircnt:20;
+       } s;
+       struct cvmx_mixx_ircnt_s cn52xx;
+       struct cvmx_mixx_ircnt_s cn52xxp1;
+       struct cvmx_mixx_ircnt_s cn56xx;
+       struct cvmx_mixx_ircnt_s cn56xxp1;
+};
+
+union cvmx_mixx_irhwm {
+       uint64_t u64;
+       struct cvmx_mixx_irhwm_s {
+               uint64_t reserved_40_63:24;
+               uint64_t ibplwm:20;
+               uint64_t irhwm:20;
+       } s;
+       struct cvmx_mixx_irhwm_s cn52xx;
+       struct cvmx_mixx_irhwm_s cn52xxp1;
+       struct cvmx_mixx_irhwm_s cn56xx;
+       struct cvmx_mixx_irhwm_s cn56xxp1;
+};
+
+union cvmx_mixx_iring1 {
+       uint64_t u64;
+       struct cvmx_mixx_iring1_s {
+               uint64_t reserved_60_63:4;
+               uint64_t isize:20;
+               uint64_t reserved_36_39:4;
+               uint64_t ibase:33;
+               uint64_t reserved_0_2:3;
+       } s;
+       struct cvmx_mixx_iring1_s cn52xx;
+       struct cvmx_mixx_iring1_s cn52xxp1;
+       struct cvmx_mixx_iring1_s cn56xx;
+       struct cvmx_mixx_iring1_s cn56xxp1;
+};
+
+union cvmx_mixx_iring2 {
+       uint64_t u64;
+       struct cvmx_mixx_iring2_s {
+               uint64_t reserved_52_63:12;
+               uint64_t itlptr:20;
+               uint64_t reserved_20_31:12;
+               uint64_t idbell:20;
+       } s;
+       struct cvmx_mixx_iring2_s cn52xx;
+       struct cvmx_mixx_iring2_s cn52xxp1;
+       struct cvmx_mixx_iring2_s cn56xx;
+       struct cvmx_mixx_iring2_s cn56xxp1;
+};
+
+union cvmx_mixx_isr {
+       uint64_t u64;
+       struct cvmx_mixx_isr_s {
+               uint64_t reserved_7_63:57;
+               uint64_t orun:1;
+               uint64_t irun:1;
+               uint64_t data_drp:1;
+               uint64_t irthresh:1;
+               uint64_t orthresh:1;
+               uint64_t idblovf:1;
+               uint64_t odblovf:1;
+       } s;
+       struct cvmx_mixx_isr_s cn52xx;
+       struct cvmx_mixx_isr_s cn52xxp1;
+       struct cvmx_mixx_isr_s cn56xx;
+       struct cvmx_mixx_isr_s cn56xxp1;
+};
+
+union cvmx_mixx_orcnt {
+       uint64_t u64;
+       struct cvmx_mixx_orcnt_s {
+               uint64_t reserved_20_63:44;
+               uint64_t orcnt:20;
+       } s;
+       struct cvmx_mixx_orcnt_s cn52xx;
+       struct cvmx_mixx_orcnt_s cn52xxp1;
+       struct cvmx_mixx_orcnt_s cn56xx;
+       struct cvmx_mixx_orcnt_s cn56xxp1;
+};
+
+union cvmx_mixx_orhwm {
+       uint64_t u64;
+       struct cvmx_mixx_orhwm_s {
+               uint64_t reserved_20_63:44;
+               uint64_t orhwm:20;
+       } s;
+       struct cvmx_mixx_orhwm_s cn52xx;
+       struct cvmx_mixx_orhwm_s cn52xxp1;
+       struct cvmx_mixx_orhwm_s cn56xx;
+       struct cvmx_mixx_orhwm_s cn56xxp1;
+};
+
+union cvmx_mixx_oring1 {
+       uint64_t u64;
+       struct cvmx_mixx_oring1_s {
+               uint64_t reserved_60_63:4;
+               uint64_t osize:20;
+               uint64_t reserved_36_39:4;
+               uint64_t obase:33;
+               uint64_t reserved_0_2:3;
+       } s;
+       struct cvmx_mixx_oring1_s cn52xx;
+       struct cvmx_mixx_oring1_s cn52xxp1;
+       struct cvmx_mixx_oring1_s cn56xx;
+       struct cvmx_mixx_oring1_s cn56xxp1;
+};
+
+union cvmx_mixx_oring2 {
+       uint64_t u64;
+       struct cvmx_mixx_oring2_s {
+               uint64_t reserved_52_63:12;
+               uint64_t otlptr:20;
+               uint64_t reserved_20_31:12;
+               uint64_t odbell:20;
+       } s;
+       struct cvmx_mixx_oring2_s cn52xx;
+       struct cvmx_mixx_oring2_s cn52xxp1;
+       struct cvmx_mixx_oring2_s cn56xx;
+       struct cvmx_mixx_oring2_s cn56xxp1;
+};
+
+union cvmx_mixx_remcnt {
+       uint64_t u64;
+       struct cvmx_mixx_remcnt_s {
+               uint64_t reserved_52_63:12;
+               uint64_t iremcnt:20;
+               uint64_t reserved_20_31:12;
+               uint64_t oremcnt:20;
+       } s;
+       struct cvmx_mixx_remcnt_s cn52xx;
+       struct cvmx_mixx_remcnt_s cn52xxp1;
+       struct cvmx_mixx_remcnt_s cn56xx;
+       struct cvmx_mixx_remcnt_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-smix-defs.h b/arch/mips/include/asm/octeon/cvmx-smix-defs.h
new file mode 100644 (file)
index 0000000..9ae45fc
--- /dev/null
@@ -0,0 +1,178 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_SMIX_DEFS_H__
+#define __CVMX_SMIX_DEFS_H__
+
+#define CVMX_SMIX_CLK(offset) \
+        CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_CMD(offset) \
+        CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_EN(offset) \
+        CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_RD_DAT(offset) \
+        CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_WR_DAT(offset) \
+        CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256))
+
+union cvmx_smix_clk {
+       uint64_t u64;
+       struct cvmx_smix_clk_s {
+               uint64_t reserved_25_63:39;
+               uint64_t mode:1;
+               uint64_t reserved_21_23:3;
+               uint64_t sample_hi:5;
+               uint64_t sample_mode:1;
+               uint64_t reserved_14_14:1;
+               uint64_t clk_idle:1;
+               uint64_t preamble:1;
+               uint64_t sample:4;
+               uint64_t phase:8;
+       } s;
+       struct cvmx_smix_clk_cn30xx {
+               uint64_t reserved_21_63:43;
+               uint64_t sample_hi:5;
+               uint64_t reserved_14_15:2;
+               uint64_t clk_idle:1;
+               uint64_t preamble:1;
+               uint64_t sample:4;
+               uint64_t phase:8;
+       } cn30xx;
+       struct cvmx_smix_clk_cn30xx cn31xx;
+       struct cvmx_smix_clk_cn30xx cn38xx;
+       struct cvmx_smix_clk_cn30xx cn38xxp2;
+       struct cvmx_smix_clk_cn50xx {
+               uint64_t reserved_25_63:39;
+               uint64_t mode:1;
+               uint64_t reserved_21_23:3;
+               uint64_t sample_hi:5;
+               uint64_t reserved_14_15:2;
+               uint64_t clk_idle:1;
+               uint64_t preamble:1;
+               uint64_t sample:4;
+               uint64_t phase:8;
+       } cn50xx;
+       struct cvmx_smix_clk_s cn52xx;
+       struct cvmx_smix_clk_cn50xx cn52xxp1;
+       struct cvmx_smix_clk_s cn56xx;
+       struct cvmx_smix_clk_cn50xx cn56xxp1;
+       struct cvmx_smix_clk_cn30xx cn58xx;
+       struct cvmx_smix_clk_cn30xx cn58xxp1;
+};
+
+union cvmx_smix_cmd {
+       uint64_t u64;
+       struct cvmx_smix_cmd_s {
+               uint64_t reserved_18_63:46;
+               uint64_t phy_op:2;
+               uint64_t reserved_13_15:3;
+               uint64_t phy_adr:5;
+               uint64_t reserved_5_7:3;
+               uint64_t reg_adr:5;
+       } s;
+       struct cvmx_smix_cmd_cn30xx {
+               uint64_t reserved_17_63:47;
+               uint64_t phy_op:1;
+               uint64_t reserved_13_15:3;
+               uint64_t phy_adr:5;
+               uint64_t reserved_5_7:3;
+               uint64_t reg_adr:5;
+       } cn30xx;
+       struct cvmx_smix_cmd_cn30xx cn31xx;
+       struct cvmx_smix_cmd_cn30xx cn38xx;
+       struct cvmx_smix_cmd_cn30xx cn38xxp2;
+       struct cvmx_smix_cmd_s cn50xx;
+       struct cvmx_smix_cmd_s cn52xx;
+       struct cvmx_smix_cmd_s cn52xxp1;
+       struct cvmx_smix_cmd_s cn56xx;
+       struct cvmx_smix_cmd_s cn56xxp1;
+       struct cvmx_smix_cmd_cn30xx cn58xx;
+       struct cvmx_smix_cmd_cn30xx cn58xxp1;
+};
+
+union cvmx_smix_en {
+       uint64_t u64;
+       struct cvmx_smix_en_s {
+               uint64_t reserved_1_63:63;
+               uint64_t en:1;
+       } s;
+       struct cvmx_smix_en_s cn30xx;
+       struct cvmx_smix_en_s cn31xx;
+       struct cvmx_smix_en_s cn38xx;
+       struct cvmx_smix_en_s cn38xxp2;
+       struct cvmx_smix_en_s cn50xx;
+       struct cvmx_smix_en_s cn52xx;
+       struct cvmx_smix_en_s cn52xxp1;
+       struct cvmx_smix_en_s cn56xx;
+       struct cvmx_smix_en_s cn56xxp1;
+       struct cvmx_smix_en_s cn58xx;
+       struct cvmx_smix_en_s cn58xxp1;
+};
+
+union cvmx_smix_rd_dat {
+       uint64_t u64;
+       struct cvmx_smix_rd_dat_s {
+               uint64_t reserved_18_63:46;
+               uint64_t pending:1;
+               uint64_t val:1;
+               uint64_t dat:16;
+       } s;
+       struct cvmx_smix_rd_dat_s cn30xx;
+       struct cvmx_smix_rd_dat_s cn31xx;
+       struct cvmx_smix_rd_dat_s cn38xx;
+       struct cvmx_smix_rd_dat_s cn38xxp2;
+       struct cvmx_smix_rd_dat_s cn50xx;
+       struct cvmx_smix_rd_dat_s cn52xx;
+       struct cvmx_smix_rd_dat_s cn52xxp1;
+       struct cvmx_smix_rd_dat_s cn56xx;
+       struct cvmx_smix_rd_dat_s cn56xxp1;
+       struct cvmx_smix_rd_dat_s cn58xx;
+       struct cvmx_smix_rd_dat_s cn58xxp1;
+};
+
+union cvmx_smix_wr_dat {
+       uint64_t u64;
+       struct cvmx_smix_wr_dat_s {
+               uint64_t reserved_18_63:46;
+               uint64_t pending:1;
+               uint64_t val:1;
+               uint64_t dat:16;
+       } s;
+       struct cvmx_smix_wr_dat_s cn30xx;
+       struct cvmx_smix_wr_dat_s cn31xx;
+       struct cvmx_smix_wr_dat_s cn38xx;
+       struct cvmx_smix_wr_dat_s cn38xxp2;
+       struct cvmx_smix_wr_dat_s cn50xx;
+       struct cvmx_smix_wr_dat_s cn52xx;
+       struct cvmx_smix_wr_dat_s cn52xxp1;
+       struct cvmx_smix_wr_dat_s cn56xx;
+       struct cvmx_smix_wr_dat_s cn56xxp1;
+       struct cvmx_smix_wr_dat_s cn58xx;
+       struct cvmx_smix_wr_dat_s cn58xxp1;
+};
+
+#endif
index cac9b1a..4d0a8c6 100644 (file)
@@ -47,6 +47,7 @@ struct octeon_cop2_state;
 extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
 extern void octeon_crypto_disable(struct octeon_cop2_state *state,
                                  unsigned long flags);
+extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
 
 extern void octeon_init_cvmcount(void);
 
index d6eb613..1854336 100644 (file)
@@ -390,6 +390,19 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
 #include <asm-generic/pgtable.h>
 
 /*
+ * uncached accelerated TLB map for video memory access
+ */
+#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+struct file;
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+               unsigned long size, pgprot_t vma_prot);
+int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+               unsigned long size, pgprot_t *vma_prot);
+#endif
+
+/*
  * We provide our own get_unmapped area to cope with the virtual aliasing
  * constraints placed on us by the cache architecture.
  */
index bfce5c7..63741ca 100644 (file)
@@ -85,8 +85,7 @@ extern void prom_identify_arch(void);
 extern PCHAR ArcGetEnvironmentVariable(PCHAR name);
 extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value);
 
-/* ARCS command line acquisition and parsing. */
-extern char *prom_getcmdline(void);
+/* ARCS command line parsing. */
 extern void prom_init_cmdline(void);
 
 /* Acquiring info about the current time, etc. */
index db0fa7b..3b6da33 100644 (file)
@@ -51,9 +51,6 @@
                LONG_S  v1, PT_ACX(sp)
 #else
                mfhi    v1
-               LONG_S  v1, PT_HI(sp)
-               mflo    v1
-               LONG_S  v1, PT_LO(sp)
 #endif
 #ifdef CONFIG_32BIT
                LONG_S  $8, PT_R8(sp)
                LONG_S  $10, PT_R10(sp)
                LONG_S  $11, PT_R11(sp)
                LONG_S  $12, PT_R12(sp)
+#ifndef CONFIG_CPU_HAS_SMARTMIPS
+               LONG_S  v1, PT_HI(sp)
+               mflo    v1
+#endif
                LONG_S  $13, PT_R13(sp)
                LONG_S  $14, PT_R14(sp)
                LONG_S  $15, PT_R15(sp)
                LONG_S  $24, PT_R24(sp)
+#ifndef CONFIG_CPU_HAS_SMARTMIPS
+               LONG_S  v1, PT_LO(sp)
+#endif
                .endm
 
                .macro  SAVE_STATIC
 #ifdef CONFIG_SMP
 #ifdef CONFIG_MIPS_MT_SMTC
 #define PTEBASE_SHIFT  19      /* TCBIND */
+#define CPU_ID_REG CP0_TCBIND
+#define CPU_ID_MFC0 mfc0
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define PTEBASE_SHIFT  48      /* XCONTEXT */
+#define CPU_ID_REG CP0_XCONTEXT
+#define CPU_ID_MFC0 MFC0
 #else
 #define PTEBASE_SHIFT  23      /* CONTEXT */
+#define CPU_ID_REG CP0_CONTEXT
+#define CPU_ID_MFC0 MFC0
 #endif
                .macro  get_saved_sp    /* SMP variation */
-#ifdef CONFIG_MIPS_MT_SMTC
-               mfc0    k0, CP0_TCBIND
-#else
-               MFC0    k0, CP0_CONTEXT
-#endif
+               CPU_ID_MFC0     k0, CPU_ID_REG
 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
                lui     k1, %hi(kernelsp)
 #else
                .endm
 
                .macro  set_saved_sp stackp temp temp2
-#ifdef CONFIG_MIPS_MT_SMTC
-               mfc0    \temp, CP0_TCBIND
-#else
-               MFC0    \temp, CP0_CONTEXT
-#endif
+               CPU_ID_MFC0     \temp, CPU_ID_REG
                LONG_SRL        \temp, PTEBASE_SHIFT
                LONG_S  \stackp, kernelsp(\temp)
                .endm
                LONG_S  $0, PT_R0(sp)
                mfc0    v1, CP0_STATUS
                LONG_S  $2, PT_R2(sp)
-               LONG_S  v1, PT_STATUS(sp)
 #ifdef CONFIG_MIPS_MT_SMTC
                /*
                 * Ideally, these instructions would be shuffled in
                LONG_S  v1, PT_TCSTATUS(sp)
 #endif /* CONFIG_MIPS_MT_SMTC */
                LONG_S  $4, PT_R4(sp)
-               mfc0    v1, CP0_CAUSE
                LONG_S  $5, PT_R5(sp)
-               LONG_S  v1, PT_CAUSE(sp)
+               LONG_S  v1, PT_STATUS(sp)
+               mfc0    v1, CP0_CAUSE
                LONG_S  $6, PT_R6(sp)
-               MFC0    v1, CP0_EPC
                LONG_S  $7, PT_R7(sp)
+               LONG_S  v1, PT_CAUSE(sp)
+               MFC0    v1, CP0_EPC
 #ifdef CONFIG_64BIT
                LONG_S  $8, PT_R8(sp)
                LONG_S  $9, PT_R9(sp)
 #endif
-               LONG_S  v1, PT_EPC(sp)
                LONG_S  $25, PT_R25(sp)
                LONG_S  $28, PT_R28(sp)
                LONG_S  $31, PT_R31(sp)
+               LONG_S  v1, PT_EPC(sp)
                ori     $28, sp, _THREAD_MASK
                xori    $28, _THREAD_MASK
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
index eecd2a9..9326af5 100644 (file)
@@ -2,14 +2,17 @@
 # Makefile for the Linux/MIPS kernel.
 #
 
-CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
-
 extra-y                := head.o init_task.o vmlinux.lds
 
 obj-y          += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
                   ptrace.o reset.o setup.o signal.o syscall.o \
                   time.o topology.o traps.o unaligned.o watch.o
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_early_printk.o = -pg
+endif
+
 obj-$(CONFIG_CEVT_BCM1480)     += cevt-bcm1480.o
 obj-$(CONFIG_CEVT_R4K_LIB)     += cevt-r4k.o
 obj-$(CONFIG_MIPS_MT_SMTC)     += cevt-smtc.o
@@ -19,6 +22,7 @@ obj-$(CONFIG_CEVT_SB1250)     += cevt-sb1250.o
 obj-$(CONFIG_CEVT_TXX9)                += cevt-txx9.o
 obj-$(CONFIG_CSRC_BCM1480)     += csrc-bcm1480.o
 obj-$(CONFIG_CSRC_IOASIC)      += csrc-ioasic.o
+obj-$(CONFIG_CSRC_POWERTV)     += csrc-powertv.o
 obj-$(CONFIG_CSRC_R4K_LIB)     += csrc-r4k.o
 obj-$(CONFIG_CSRC_SB1250)      += csrc-sb1250.o
 obj-$(CONFIG_SYNC_R4K)         += sync-r4k.o
@@ -26,6 +30,8 @@ obj-$(CONFIG_SYNC_R4K)                += sync-r4k.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_MODULES)          += mips_ksyms.o module.o
 
+obj-$(CONFIG_FUNCTION_TRACER)  += mcount.o ftrace.o
+
 obj-$(CONFIG_CPU_LOONGSON2)    += r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS32)       += r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS64)       += r4k_fpu.o r4k_switch.o
@@ -92,4 +98,8 @@ CFLAGS_cpu-bugs64.o   = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/n
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)  += 8250-platform.o
 
+obj-$(CONFIG_MIPS_CPUFREQ)     += cpufreq/
+
 EXTRA_CFLAGS += -Werror
+
+CPPFLAGS_vmlinux.lds           := $(KBUILD_CFLAGS)
index 7a51866..80e202e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
@@ -32,6 +33,7 @@
  * the CPU very much.
  */
 void (*cpu_wait)(void);
+EXPORT_SYMBOL(cpu_wait);
 
 static void r3081_wait(void)
 {
diff --git a/arch/mips/kernel/cpufreq/Kconfig b/arch/mips/kernel/cpufreq/Kconfig
new file mode 100644 (file)
index 0000000..58c601e
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# CPU Frequency scaling
+#
+
+config MIPS_EXTERNAL_TIMER
+       bool
+
+config MIPS_CPUFREQ
+       bool
+       default y
+       depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
+
+if MIPS_CPUFREQ
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+if CPU_FREQ
+
+comment "CPUFreq processor drivers"
+
+config LOONGSON2_CPUFREQ
+       tristate "Loongson2 CPUFreq Driver"
+       select CPU_FREQ_TABLE
+       depends on MIPS_CPUFREQ
+       help
+         This option adds a CPUFreq driver for loongson processors which
+         support software configurable cpu frequency.
+
+         Loongson2F and it's successors support this feature.
+
+         For details, take a look at <file:Documentation/cpu-freq/>.
+
+         If in doubt, say N.
+
+endif  # CPU_FREQ
+
+endmenu
+
+endif  # MIPS_CPUFREQ
diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile
new file mode 100644 (file)
index 0000000..c3479a4
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Linux/MIPS cpufreq.
+#
+
+obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o
diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c
new file mode 100644 (file)
index 0000000..d7ca256
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.com
+ *
+ * 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 <linux/cpufreq.h>
+#include <linux/platform_device.h>
+
+#include <asm/clock.h>
+
+#include <loongson.h>
+
+static LIST_HEAD(clock_list);
+static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(clock_list_sem);
+
+/* Minimum CLK support */
+enum {
+       DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
+       DC_87PT, DC_DISABLE, DC_RESV
+};
+
+struct cpufreq_frequency_table loongson2_clockmod_table[] = {
+       {DC_RESV, CPUFREQ_ENTRY_INVALID},
+       {DC_ZERO, CPUFREQ_ENTRY_INVALID},
+       {DC_25PT, 0},
+       {DC_37PT, 0},
+       {DC_50PT, 0},
+       {DC_62PT, 0},
+       {DC_75PT, 0},
+       {DC_87PT, 0},
+       {DC_DISABLE, 0},
+       {DC_RESV, CPUFREQ_TABLE_END},
+};
+EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
+
+static struct clk cpu_clk = {
+       .name = "cpu_clk",
+       .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
+       .rate = 800000000,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       return &cpu_clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+static void propagate_rate(struct clk *clk)
+{
+       struct clk *clkp;
+
+       list_for_each_entry(clkp, &clock_list, node) {
+               if (likely(clkp->parent != clk))
+                       continue;
+               if (likely(clkp->ops && clkp->ops->recalc))
+                       clkp->ops->recalc(clkp);
+               if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
+                       propagate_rate(clkp);
+       }
+}
+
+int clk_enable(struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return (unsigned long)clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return clk_set_rate_ex(clk, rate, 0);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
+{
+       int ret = 0;
+       int regval;
+       int i;
+
+       if (likely(clk->ops && clk->ops->set_rate)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&clock_lock, flags);
+               ret = clk->ops->set_rate(clk, rate, algo_id);
+               spin_unlock_irqrestore(&clock_lock, flags);
+       }
+
+       if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+               propagate_rate(clk);
+
+       for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
+            i++) {
+               if (loongson2_clockmod_table[i].frequency ==
+                   CPUFREQ_ENTRY_INVALID)
+                       continue;
+               if (rate == loongson2_clockmod_table[i].frequency)
+                       break;
+       }
+       if (rate != loongson2_clockmod_table[i].frequency)
+               return -ENOTSUPP;
+
+       clk->rate = rate;
+
+       regval = LOONGSON_CHIPCFG0;
+       regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
+       LOONGSON_CHIPCFG0 = regval;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate_ex);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (likely(clk->ops && clk->ops->round_rate)) {
+               unsigned long flags, rounded;
+
+               spin_lock_irqsave(&clock_lock, flags);
+               rounded = clk->ops->round_rate(clk, rate);
+               spin_unlock_irqrestore(&clock_lock, flags);
+
+               return rounded;
+       }
+
+       return rate;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/*
+ * This is the simple version of Loongson-2 wait, Maybe we need do this in
+ * interrupt disabled content
+ */
+
+DEFINE_SPINLOCK(loongson2_wait_lock);
+void loongson2_cpu_wait(void)
+{
+       u32 cpu_freq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&loongson2_wait_lock, flags);
+       cpu_freq = LOONGSON_CHIPCFG0;
+       LOONGSON_CHIPCFG0 &= ~0x7;      /* Put CPU into wait mode */
+       LOONGSON_CHIPCFG0 = cpu_freq;   /* Restore CPU state */
+       spin_unlock_irqrestore(&loongson2_wait_lock, flags);
+}
+EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
new file mode 100644 (file)
index 0000000..2f6a0b1
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Cpufreq driver for the loongson-2 processors
+ *
+ * The 2E revision of loongson processor not support this feature.
+ *
+ * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.com
+ *
+ * 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 <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sched.h>       /* set_cpus_allowed() */
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <asm/clock.h>
+
+#include <loongson.h>
+
+static uint nowait;
+
+static struct clk *cpuclk;
+
+static void (*saved_cpu_wait) (void);
+
+static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
+                                       unsigned long val, void *data);
+
+static struct notifier_block loongson2_cpufreq_notifier_block = {
+       .notifier_call = loongson2_cpu_freq_notifier
+};
+
+static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
+                                       unsigned long val, void *data)
+{
+       if (val == CPUFREQ_POSTCHANGE)
+               current_cpu_data.udelay_val = loops_per_jiffy;
+
+       return 0;
+}
+
+static unsigned int loongson2_cpufreq_get(unsigned int cpu)
+{
+       return clk_get_rate(cpuclk);
+}
+
+/*
+ * Here we notify other drivers of the proposed change and the final change.
+ */
+static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
+                                    unsigned int target_freq,
+                                    unsigned int relation)
+{
+       unsigned int cpu = policy->cpu;
+       unsigned int newstate = 0;
+       cpumask_t cpus_allowed;
+       struct cpufreq_freqs freqs;
+       unsigned int freq;
+
+       if (!cpu_online(cpu))
+               return -ENODEV;
+
+       cpus_allowed = current->cpus_allowed;
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+       if (cpufreq_frequency_table_target
+           (policy, &loongson2_clockmod_table[0], target_freq, relation,
+            &newstate))
+               return -EINVAL;
+
+       freq =
+           ((cpu_clock_freq / 1000) *
+            loongson2_clockmod_table[newstate].index) / 8;
+       if (freq < policy->min || freq > policy->max)
+               return -EINVAL;
+
+       pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+
+       freqs.cpu = cpu;
+       freqs.old = loongson2_cpufreq_get(cpu);
+       freqs.new = freq;
+       freqs.flags = 0;
+
+       if (freqs.new == freqs.old)
+               return 0;
+
+       /* notifiers */
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       set_cpus_allowed(current, cpus_allowed);
+
+       /* setting the cpu frequency */
+       clk_set_rate(cpuclk, freq);
+
+       /* notifiers */
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       pr_debug("cpufreq: set frequency %u kHz\n", freq);
+
+       return 0;
+}
+
+static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+       int i;
+
+       if (!cpu_online(policy->cpu))
+               return -ENODEV;
+
+       cpuclk = clk_get(NULL, "cpu_clk");
+       if (IS_ERR(cpuclk)) {
+               printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
+               return PTR_ERR(cpuclk);
+       }
+
+       cpuclk->rate = cpu_clock_freq / 1000;
+       if (!cpuclk->rate)
+               return -EINVAL;
+
+       /* clock table init */
+       for (i = 2;
+            (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
+            i++)
+               loongson2_clockmod_table[i].frequency = (cpuclk->rate * i) / 8;
+
+       policy->cur = loongson2_cpufreq_get(policy->cpu);
+
+       cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
+                                        policy->cpu);
+
+       return cpufreq_frequency_table_cpuinfo(policy,
+                                           &loongson2_clockmod_table[0]);
+}
+
+static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy,
+                                             &loongson2_clockmod_table[0]);
+}
+
+static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
+{
+       clk_put(cpuclk);
+       return 0;
+}
+
+static struct freq_attr *loongson2_table_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver loongson2_cpufreq_driver = {
+       .owner = THIS_MODULE,
+       .name = "loongson2",
+       .init = loongson2_cpufreq_cpu_init,
+       .verify = loongson2_cpufreq_verify,
+       .target = loongson2_cpufreq_target,
+       .get = loongson2_cpufreq_get,
+       .exit = loongson2_cpufreq_exit,
+       .attr = loongson2_table_attr,
+};
+
+static struct platform_device_id platform_device_ids[] = {
+       {
+               .name = "loongson2_cpufreq",
+       },
+       {}
+};
+
+MODULE_DEVICE_TABLE(platform, platform_device_ids);
+
+static struct platform_driver platform_driver = {
+       .driver = {
+               .name = "loongson2_cpufreq",
+               .owner = THIS_MODULE,
+       },
+       .id_table = platform_device_ids,
+};
+
+static int __init cpufreq_init(void)
+{
+       int ret;
+
+       /* Register platform stuff */
+       ret = platform_driver_register(&platform_driver);
+       if (ret)
+               return ret;
+
+       pr_info("cpufreq: Loongson-2F CPU frequency driver.\n");
+
+       cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
+                                 CPUFREQ_TRANSITION_NOTIFIER);
+
+       ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
+
+       if (!ret && !nowait) {
+               saved_cpu_wait = cpu_wait;
+               cpu_wait = loongson2_cpu_wait;
+       }
+
+       return ret;
+}
+
+static void __exit cpufreq_exit(void)
+{
+       if (!nowait && saved_cpu_wait)
+               cpu_wait = saved_cpu_wait;
+       cpufreq_unregister_driver(&loongson2_cpufreq_driver);
+       cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+
+       platform_driver_unregister(&platform_driver);
+}
+
+module_init(cpufreq_init);
+module_exit(cpufreq_exit);
+
+module_param(nowait, uint, 0644);
+MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
+
+MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
+MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
new file mode 100644 (file)
index 0000000..a27c16c
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This 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 file comes from kernel/csrc-r4k.c
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+
+#include <asm/time.h>                  /* Not included in linux/time.h */
+
+#include <asm/mach-powertv/asic_regs.h>
+#include "powertv-clock.h"
+
+/* MIPS PLL Register Definitions */
+#define PLL_GET_M(x)           (((x) >> 8) & 0x000000FF)
+#define PLL_GET_N(x)           (((x) >> 16) & 0x000000FF)
+#define PLL_GET_P(x)           (((x) >> 24) & 0x00000007)
+
+/*
+ * returns:  Clock frequency in kHz
+ */
+unsigned int __init mips_get_pll_freq(void)
+{
+       unsigned int pll_reg, m, n, p;
+       unsigned int fin = 54000; /* Base frequency in kHz */
+       unsigned int fout;
+
+       /* Read PLL register setting */
+       pll_reg = asic_read(mips_pll_setup);
+       m = PLL_GET_M(pll_reg);
+       n = PLL_GET_N(pll_reg);
+       p = PLL_GET_P(pll_reg);
+       pr_info("MIPS PLL Register:0x%x  M=%d  N=%d  P=%d\n", pll_reg, m, n, p);
+
+       /* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
+       fout = ((2 * n * fin) / (m * (0x01 << p)));
+
+       pr_info("MIPS Clock Freq=%d kHz\n", fout);
+
+       return fout;
+}
+
+static cycle_t c0_hpt_read(struct clocksource *cs)
+{
+       return read_c0_count();
+}
+
+static struct clocksource clocksource_mips = {
+       .name           = "powertv-counter",
+       .read           = c0_hpt_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init powertv_c0_hpt_clocksource_init(void)
+{
+       unsigned int pll_freq = mips_get_pll_freq();
+
+       pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
+               (pll_freq % 1000) * 100 / 1000);
+
+       mips_hpt_frequency = pll_freq / 2 * 1000;
+
+       clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
+
+       clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
+
+       clocksource_register(&clocksource_mips);
+}
+
+/**
+ * struct tim_c - free running counter
+ * @hi:        High 16 bits of the counter
+ * @lo:        Low 32 bits of the counter
+ *
+ * Lays out the structure of the free running counter in memory. This counter
+ * increments at a rate of 27 MHz/8 on all platforms.
+ */
+struct tim_c {
+       unsigned int hi;
+       unsigned int lo;
+};
+
+static struct tim_c *tim_c;
+
+static cycle_t tim_c_read(struct clocksource *cs)
+{
+       unsigned int hi;
+       unsigned int next_hi;
+       unsigned int lo;
+
+       hi = readl(&tim_c->hi);
+
+       for (;;) {
+               lo = readl(&tim_c->lo);
+               next_hi = readl(&tim_c->hi);
+               if (next_hi == hi)
+                       break;
+               hi = next_hi;
+       }
+
+pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
+       return ((u64) hi << 32) | lo;
+}
+
+#define TIM_C_SIZE             48              /* # bits in the timer */
+
+static struct clocksource clocksource_tim_c = {
+       .name           = "powertv-tim_c",
+       .read           = tim_c_read,
+       .mask           = CLOCKSOURCE_MASK(TIM_C_SIZE),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/**
+ * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
+ *
+ * The hard part here is coming up with a constant k and shift s such that
+ * the 48-bit TIM_C value multiplied by k doesn't overflow and that value,
+ * when shifted right by s, yields the corresponding number of nanoseconds.
+ * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
+ * 1 / (27,000,000/8) seconds. Multiply that by a billion and you get the
+ * number of nanoseconds. Since the TIM_C value has 48 bits and the math is
+ * done in 64 bits, avoiding an overflow means that k must be less than
+ * 64 - 48 = 16 bits.
+ */
+static void __init powertv_tim_c_clocksource_init(void)
+{
+       int                     prescale;
+       unsigned long           dividend;
+       unsigned long           k;
+       int                     s;
+       const int               max_k_bits = (64 - 48) - 1;
+       const unsigned long     billion = 1000000000;
+       const unsigned long     counts_per_second = 27000000 / 8;
+
+       prescale = BITS_PER_LONG - ilog2(billion) - 1;
+       dividend = billion << prescale;
+       k = dividend / counts_per_second;
+       s = ilog2(k) - max_k_bits;
+
+       if (s < 0)
+               s = prescale;
+
+       else {
+               k >>= s;
+               s += prescale;
+       }
+
+       clocksource_tim_c.mult = k;
+       clocksource_tim_c.shift = s;
+       clocksource_tim_c.rating = 200;
+
+       clocksource_register(&clocksource_tim_c);
+       tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
+}
+
+/**
+ powertv_clocksource_init - initialize all clocksources
+ */
+void __init powertv_clocksource_init(void)
+{
+       powertv_c0_hpt_clocksource_init();
+       powertv_tim_c_clocksource_init();
+}
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
new file mode 100644 (file)
index 0000000..68b0670
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Code for replacing ftrace calls with jumps.
+ *
+ * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * Thanks goes to Steven Rostedt for writing the original x86 version.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define JAL 0x0c000000         /* jump & link: ip --> ra, jump to target */
+#define ADDR_MASK 0x03ffffff   /*  op_code|addr : 31...26|25 ....0 */
+#define jump_insn_encode(op_code, addr) \
+       ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
+
+static unsigned int ftrace_nop = 0x00000000;
+
+static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
+{
+       int faulted;
+
+       /* *(unsigned int *)ip = new_code; */
+       safe_store_code(new_code, ip, faulted);
+
+       if (unlikely(faulted))
+               return -EFAULT;
+
+       flush_icache_range(ip, ip + 8);
+
+       return 0;
+}
+
+static int lui_v1;
+static int jal_mcount;
+
+int ftrace_make_nop(struct module *mod,
+                   struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned int new;
+       int faulted;
+       unsigned long ip = rec->ip;
+
+       /* We have compiled module with -mlong-calls, but compiled the kernel
+        * without it, we need to cope with them respectively. */
+       if (ip & 0x40000000) {
+               /* record it for ftrace_make_call */
+               if (lui_v1 == 0) {
+                       /* lui_v1 = *(unsigned int *)ip; */
+                       safe_load_code(lui_v1, ip, faulted);
+
+                       if (unlikely(faulted))
+                               return -EFAULT;
+               }
+
+               /* lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
+                * addiu v1, v1, low_16bit_of_mcount
+                * move at, ra
+                * jalr v1
+                * nop
+                *                                   1f: (ip + 12)
+                */
+               new = 0x10000004;
+       } else {
+               /* record/calculate it for ftrace_make_call */
+               if (jal_mcount == 0) {
+                       /* We can record it directly like this:
+                        *     jal_mcount = *(unsigned int *)ip;
+                        * Herein, jump over the first two nop instructions */
+                       jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
+               }
+
+               /* move at, ra
+                * jalr v1              --> nop
+                */
+               new = ftrace_nop;
+       }
+       return ftrace_modify_code(ip, new);
+}
+
+static int modified;   /* initialized as 0 by default */
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned int new;
+       unsigned long ip = rec->ip;
+
+       /* We just need to remove the "b ftrace_stub" at the fist time! */
+       if (modified == 0) {
+               modified = 1;
+               ftrace_modify_code(addr, ftrace_nop);
+       }
+       /* ip, module: 0xc0000000, kernel: 0x80000000 */
+       new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
+
+       return ftrace_modify_code(ip, new);
+}
+
+#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+       unsigned int new;
+
+       new = jump_insn_encode(JAL, (unsigned long)func);
+
+       return ftrace_modify_code(FTRACE_CALL_IP, new);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+       /* The return code is retured via data */
+       *(unsigned long *)data = 0;
+
+       return 0;
+}
+#endif                         /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+extern void ftrace_graph_call(void);
+#define JMP    0x08000000      /* jump to target directly */
+#define CALL_FTRACE_GRAPH_CALLER \
+       jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
+#define FTRACE_GRAPH_CALL_IP   ((unsigned long)(&ftrace_graph_call))
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+       return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
+                                 CALL_FTRACE_GRAPH_CALLER);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+       return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop);
+}
+
+#endif                         /* !CONFIG_DYNAMIC_FTRACE */
+
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
+#define S_RA_SP        (0xafbf << 16)  /* s{d,w} ra, offset(sp) */
+#define S_R_SP (0xafb0 << 16)  /* s{d,w} R, offset(sp) */
+#define OFFSET_MASK    0xffff  /* stack offset range: 0 ~ PT_SIZE */
+
+unsigned long ftrace_get_parent_addr(unsigned long self_addr,
+                                    unsigned long parent,
+                                    unsigned long parent_addr,
+                                    unsigned long fp)
+{
+       unsigned long sp, ip, ra;
+       unsigned int code;
+       int faulted;
+
+       /* in module or kernel? */
+       if (self_addr & 0x40000000) {
+               /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */
+               ip = self_addr - 20;
+       } else {
+               /* kernel: move to the instruction "move ra, at" */
+               ip = self_addr - 12;
+       }
+
+       /* search the text until finding the non-store instruction or "s{d,w}
+        * ra, offset(sp)" instruction */
+       do {
+               ip -= 4;
+
+               /* get the code at "ip": code = *(unsigned int *)ip; */
+               safe_load_code(code, ip, faulted);
+
+               if (unlikely(faulted))
+                       return 0;
+
+               /* If we hit the non-store instruction before finding where the
+                * ra is stored, then this is a leaf function and it does not
+                * store the ra on the stack. */
+               if ((code & S_R_SP) != S_R_SP)
+                       return parent_addr;
+
+       } while (((code & S_RA_SP) != S_RA_SP));
+
+       sp = fp + (code & OFFSET_MASK);
+
+       /* ra = *(unsigned long *)sp; */
+       safe_load_stack(ra, sp, faulted);
+       if (unlikely(faulted))
+               return 0;
+
+       if (ra == parent)
+               return sp;
+       return 0;
+}
+
+#endif
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+                          unsigned long fp)
+{
+       unsigned long old;
+       struct ftrace_graph_ent trace;
+       unsigned long return_hooker = (unsigned long)
+           &return_to_handler;
+       int faulted;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       /* "parent" is the stack address saved the return address of the caller
+        * of _mcount.
+        *
+        * if the gcc < 4.5, a leaf function does not save the return address
+        * in the stack address, so, we "emulate" one in _mcount's stack space,
+        * and hijack it directly, but for a non-leaf function, it save the
+        * return address to the its own stack space, we can not hijack it
+        * directly, but need to find the real stack address,
+        * ftrace_get_parent_addr() does it!
+        *
+        * if gcc>= 4.5, with the new -mmcount-ra-address option, for a
+        * non-leaf function, the location of the return address will be saved
+        * to $12 for us, and for a leaf function, only put a zero into $12. we
+        * do it in ftrace_graph_caller of mcount.S.
+        */
+
+       /* old = *parent; */
+       safe_load_stack(old, parent, faulted);
+       if (unlikely(faulted))
+               goto out;
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
+       parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
+                                                        (unsigned long)parent,
+                                                        fp);
+       /* If fails when getting the stack address of the non-leaf function's
+        * ra, stop function graph tracer and return */
+       if (parent == 0)
+               goto out;
+#endif
+       /* *parent = return_hooker; */
+       safe_store_stack(return_hooker, parent, faulted);
+       if (unlikely(faulted))
+               goto out;
+
+       if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
+           -EBUSY) {
+               *parent = old;
+               return;
+       }
+
+       trace.func = self_addr;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               *parent = old;
+       }
+       return;
+out:
+       ftrace_graph_stop();
+       WARN_ON(1);
+}
+#endif                         /* CONFIG_FUNCTION_GRAPH_TRACER */
index 8b0b418..981f86c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
 #include <linux/kgdb.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/system.h>
@@ -150,3 +151,32 @@ void __init init_IRQ(void)
                kgdb_early_setup = 1;
 #endif
 }
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+void __irq_entry do_IRQ(unsigned int irq)
+{
+       irq_enter();
+       __DO_IRQ_SMTC_HOOK(irq);
+       generic_handle_irq(irq);
+       irq_exit();
+}
+
+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
+/*
+ * To avoid inefficient and in some cases pathological re-checking of
+ * IRQ affinity, we have this variant that skips the affinity check.
+ */
+
+void __irq_entry do_IRQ_no_affinity(unsigned int irq)
+{
+       irq_enter();
+       __NO_AFFINITY_IRQ_SMTC_HOOK(irq);
+       generic_handle_irq(irq);
+       irq_exit();
+}
+
+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
new file mode 100644 (file)
index 0000000..0a9cfdb
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * MIPS specific _mcount support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/ftrace.h>
+
+       .text
+       .set noreorder
+       .set noat
+
+       .macro MCOUNT_SAVE_REGS
+       PTR_SUBU        sp, PT_SIZE
+       PTR_S   ra, PT_R31(sp)
+       PTR_S   AT, PT_R1(sp)
+       PTR_S   a0, PT_R4(sp)
+       PTR_S   a1, PT_R5(sp)
+       PTR_S   a2, PT_R6(sp)
+       PTR_S   a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+       PTR_S   a4, PT_R8(sp)
+       PTR_S   a5, PT_R9(sp)
+       PTR_S   a6, PT_R10(sp)
+       PTR_S   a7, PT_R11(sp)
+#endif
+       .endm
+
+       .macro MCOUNT_RESTORE_REGS
+       PTR_L   ra, PT_R31(sp)
+       PTR_L   AT, PT_R1(sp)
+       PTR_L   a0, PT_R4(sp)
+       PTR_L   a1, PT_R5(sp)
+       PTR_L   a2, PT_R6(sp)
+       PTR_L   a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+       PTR_L   a4, PT_R8(sp)
+       PTR_L   a5, PT_R9(sp)
+       PTR_L   a6, PT_R10(sp)
+       PTR_L   a7, PT_R11(sp)
+#endif
+#ifdef CONFIG_64BIT
+       PTR_ADDIU       sp, PT_SIZE
+#else
+       PTR_ADDIU       sp, (PT_SIZE + 8)
+#endif
+.endm
+
+       .macro RETURN_BACK
+       jr ra
+        move ra, AT
+       .endm
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+NESTED(ftrace_caller, PT_SIZE, ra)
+       .globl _mcount
+_mcount:
+       b       ftrace_stub
+        nop
+       lw      t1, function_trace_stop
+       bnez    t1, ftrace_stub
+        nop
+
+       MCOUNT_SAVE_REGS
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+       PTR_S   t0, PT_R12(sp)  /* t0 saved the location of the return address(at) by -mmcount-ra-address */
+#endif
+
+       move    a0, ra          /* arg1: next ip, selfaddr */
+       .globl ftrace_call
+ftrace_call:
+       nop     /* a placeholder for the call to a real tracing function */
+        move   a1, AT          /* arg2: the caller's next ip, parent */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl ftrace_graph_call
+ftrace_graph_call:
+       nop
+        nop
+#endif
+
+       MCOUNT_RESTORE_REGS
+       .globl ftrace_stub
+ftrace_stub:
+       RETURN_BACK
+       END(ftrace_caller)
+
+#else  /* ! CONFIG_DYNAMIC_FTRACE */
+
+NESTED(_mcount, PT_SIZE, ra)
+       lw      t1, function_trace_stop
+       bnez    t1, ftrace_stub
+        nop
+       PTR_LA  t1, ftrace_stub
+       PTR_L   t2, ftrace_trace_function /* Prepare t2 for (1) */
+       bne     t1, t2, static_trace
+        nop
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       PTR_L   t3, ftrace_graph_return
+       bne     t1, t3, ftrace_graph_caller
+        nop
+       PTR_LA  t1, ftrace_graph_entry_stub
+       PTR_L   t3, ftrace_graph_entry
+       bne     t1, t3, ftrace_graph_caller
+        nop
+#endif
+       b       ftrace_stub
+        nop
+
+static_trace:
+       MCOUNT_SAVE_REGS
+
+       move    a0, ra          /* arg1: next ip, selfaddr */
+       jalr    t2              /* (1) call *ftrace_trace_function */
+        move   a1, AT          /* arg2: the caller's next ip, parent */
+
+       MCOUNT_RESTORE_REGS
+       .globl ftrace_stub
+ftrace_stub:
+       RETURN_BACK
+       END(_mcount)
+
+#endif /* ! CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+NESTED(ftrace_graph_caller, PT_SIZE, ra)
+#ifdef CONFIG_DYNAMIC_FTRACE
+       PTR_L   a1, PT_R31(sp)  /* load the original ra from the stack */
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+       PTR_L   t0, PT_R12(sp)  /* load the original t0 from the stack */
+#endif
+#else
+       MCOUNT_SAVE_REGS
+       move    a1, ra          /* arg2: next ip, selfaddr */
+#endif
+
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+       bnez    t0, 1f          /* non-leaf func: t0 saved the location of the return address */
+        nop
+       PTR_LA  t0, PT_R1(sp)   /* leaf func: get the location of at(old ra) from our own stack */
+1:     move    a0, t0          /* arg1: the location of the return address */
+#else
+       PTR_LA  a0, PT_R1(sp)   /* arg1: &AT -> a0 */
+#endif
+       jal     prepare_ftrace_return
+#ifdef CONFIG_FRAME_POINTER
+        move   a2, fp          /* arg3: frame pointer */
+#else
+#ifdef CONFIG_64BIT
+        PTR_LA a2, PT_SIZE(sp)
+#else
+        PTR_LA a2, (PT_SIZE+8)(sp)
+#endif
+#endif
+
+       MCOUNT_RESTORE_REGS
+       RETURN_BACK
+       END(ftrace_graph_caller)
+
+       .align  2
+       .globl  return_to_handler
+return_to_handler:
+       PTR_SUBU        sp, PT_SIZE
+       PTR_S   v0, PT_R2(sp)
+
+       jal     ftrace_return_to_handler
+        PTR_S  v1, PT_R3(sp)
+
+       /* restore the real parent address: v0 -> ra */
+       move    ra, v0
+
+       PTR_L   v0, PT_R2(sp)
+       PTR_L   v1, PT_R3(sp)
+       jr      ra
+        PTR_ADDIU      sp, PT_SIZE
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+       .set at
+       .set reorder
index 225755d..1d04807 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <asm/ftrace.h>
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -51,3 +52,7 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_partial_copy_user);
 
 EXPORT_SYMBOL(invalid_pte_table);
+#ifdef CONFIG_FUNCTION_TRACER
+/* _mcount is defined in arch/mips/kernel/mcount.S */
+EXPORT_SYMBOL(_mcount);
+#endif
index 2b290d7..f9513f9 100644 (file)
@@ -58,8 +58,12 @@ EXPORT_SYMBOL(mips_machtype);
 
 struct boot_mem_map boot_mem_map;
 
-static char command_line[CL_SIZE];
-       char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE;
+static char __initdata command_line[COMMAND_LINE_SIZE];
+char __initdata arcs_cmdline[COMMAND_LINE_SIZE];
+
+#ifdef CONFIG_CMDLINE_BOOL
+static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+#endif
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
@@ -166,26 +170,8 @@ static unsigned long __init init_initrd(void)
         * already set up initrd_start and initrd_end. In these cases
         * perfom sanity checks and use them if all looks good.
         */
-       if (!initrd_start || initrd_end <= initrd_start) {
-#ifdef CONFIG_PROBE_INITRD_HEADER
-               u32 *initrd_header;
-
-               /*
-                * See if initrd has been added to the kernel image by
-                * arch/mips/boot/addinitrd.c. In that case a header is
-                * prepended to initrd and is made up by 8 bytes. The first
-                * word is a magic number and the second one is the size of
-                * initrd.  Initrd start must be page aligned in any cases.
-                */
-               initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
-               if (initrd_header[0] != 0x494E5244)
-                       goto disable;
-               initrd_start = (unsigned long)(initrd_header + 2);
-               initrd_end = initrd_start + initrd_header[1];
-#else
+       if (!initrd_start || initrd_end <= initrd_start)
                goto disable;
-#endif
-       }
 
        if (initrd_start & ~PAGE_MASK) {
                pr_err("initrd start must be page aligned\n");
@@ -476,8 +462,20 @@ static void __init arch_mem_init(char **cmdline_p)
        pr_info("Determined physical RAM map:\n");
        print_memory_map();
 
-       strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-       strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERRIDE
+       strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+#else
+       if (builtin_cmdline[0]) {
+               strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
+               strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+       }
+       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+#else
+       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+       strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 
        *cmdline_p = command_line;
 
index 6254041..d0c68b5 100644 (file)
 
 #include "signal-common.h"
 
+static int (*save_fp_context)(struct sigcontext __user *sc);
+static int (*restore_fp_context)(struct sigcontext __user *sc);
+
+extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
+
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
+
 /*
  * Horribly complicated - with the bloody RM9000 workarounds enabled
  * the signal trampolines is moving to the end of the structure so we can
@@ -709,3 +718,40 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
                        key_replace_session_keyring();
        }
 }
+
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext __user *sc)
+{
+       return raw_cpu_has_fpu
+              ? _save_fp_context(sc)
+              : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext __user *sc)
+{
+       return raw_cpu_has_fpu
+              ? _restore_fp_context(sc)
+              : fpu_emulator_restore_context(sc);
+}
+#endif
+
+static int signal_setup(void)
+{
+#ifdef CONFIG_SMP
+       /* For now just do the cpu_has_fpu check when the functions are invoked */
+       save_fp_context = smp_save_fp_context;
+       restore_fp_context = smp_restore_fp_context;
+#else
+       if (cpu_has_fpu) {
+               save_fp_context = _save_fp_context;
+               restore_fp_context = _restore_fp_context;
+       } else {
+               save_fp_context = fpu_emulator_save_context;
+               restore_fp_context = fpu_emulator_restore_context;
+       }
+#endif
+
+       return 0;
+}
+
+arch_initcall(signal_setup);
index 2e74075..03abaf0 100644 (file)
 
 #include "signal-common.h"
 
+static int (*save_fp_context32)(struct sigcontext32 __user *sc);
+static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
+
+extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
+
+extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
+
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
@@ -828,3 +837,18 @@ SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
        info.si_code |= __SI_CHLD;
        return copy_siginfo_to_user32(uinfo, &info);
 }
+
+static int signal32_init(void)
+{
+       if (cpu_has_fpu) {
+               save_fp_context32 = _save_fp_context32;
+               restore_fp_context32 = _restore_fp_context32;
+       } else {
+               save_fp_context32 = fpu_emulator_save_context32;
+               restore_fp_context32 = fpu_emulator_restore_context32;
+       }
+
+       return 0;
+}
+
+arch_initcall(signal32_init);
index e72e684..6cdca19 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/cpumask.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/cpu.h>
@@ -130,7 +131,7 @@ asmlinkage __cpuinit void start_secondary(void)
 /*
  * Call into both interrupt handlers, as we share the IPI for them
  */
-void smp_call_function_interrupt(void)
+void __irq_entry smp_call_function_interrupt(void)
 {
        irq_enter();
        generic_smp_call_function_single_interrupt();
index a38e3ee..23499b5 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
@@ -939,23 +940,29 @@ static void ipi_call_interrupt(void)
 
 DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
-void ipi_decode(struct smtc_ipi *pipi)
+static void __irq_entry smtc_clock_tick_interrupt(void)
 {
        unsigned int cpu = smp_processor_id();
        struct clock_event_device *cd;
+       int irq = MIPS_CPU_IRQ_BASE + 1;
+
+       irq_enter();
+       kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+       cd = &per_cpu(mips_clockevent_device, cpu);
+       cd->event_handler(cd);
+       irq_exit();
+}
+
+void ipi_decode(struct smtc_ipi *pipi)
+{
        void *arg_copy = pipi->arg;
        int type_copy = pipi->type;
-       int irq = MIPS_CPU_IRQ_BASE + 1;
 
        smtc_ipi_nq(&freeIPIq, pipi);
 
        switch (type_copy) {
        case SMTC_CLOCK_TICK:
-               irq_enter();
-               kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
-               cd = &per_cpu(mips_clockevent_device, cpu);
-               cd->event_handler(cd);
-               irq_exit();
+               smtc_clock_tick_interrupt();
                break;
 
        case LINUX_SMP_IPI:
index 0a18b4c..308e434 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
+#include <linux/notifier.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
 #include <asm/break.h>
+#include <asm/cop2.h>
 #include <asm/cpu.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
@@ -79,10 +81,6 @@ extern asmlinkage void handle_reserved(void);
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
        struct mips_fpu_struct *ctx, int has_fpu);
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
-#endif
-
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
@@ -857,6 +855,44 @@ static void mt_ase_fp_affinity(void)
 #endif /* CONFIG_MIPS_MT_FPAFF */
 }
 
+/*
+ * No lock; only written during early bootup by CPU 0.
+ */
+static RAW_NOTIFIER_HEAD(cu2_chain);
+
+int __ref register_cu2_notifier(struct notifier_block *nb)
+{
+       return raw_notifier_chain_register(&cu2_chain, nb);
+}
+
+int cu2_notifier_call_chain(unsigned long val, void *v)
+{
+       return raw_notifier_call_chain(&cu2_chain, val, v);
+}
+
+static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
+        void *data)
+{
+       struct pt_regs *regs = data;
+
+       switch (action) {
+       default:
+               die_if_kernel("Unhandled kernel unaligned access or invalid "
+                             "instruction", regs);
+               /* Fall through  */
+
+       case CU2_EXCEPTION:
+               force_sig(SIGILL, current);
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block default_cu2_notifier = {
+       .notifier_call  = default_cu2_call,
+       .priority       = 0x80000000,           /* Run last  */
+};
+
 asmlinkage void do_cpu(struct pt_regs *regs)
 {
        unsigned int __user *epc;
@@ -920,17 +956,9 @@ asmlinkage void do_cpu(struct pt_regs *regs)
                return;
 
        case 2:
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-               prefetch(&current->thread.cp2);
-               local_irq_save(flags);
-               KSTK_STATUS(current) |= ST0_CU2;
-               status = read_c0_status();
-               write_c0_status(status | ST0_CU2);
-               octeon_cop2_restore(&(current->thread.cp2));
-               write_c0_status(status & ~ST0_CU2);
-               local_irq_restore(flags);
-               return;
-#endif
+               raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
+               break;
+
        case 3:
                break;
        }
@@ -1367,77 +1395,6 @@ void *set_vi_handler(int n, vi_handler_t addr)
        return set_vi_srs_handler(n, addr, 0);
 }
 
-/*
- * This is used by native signal handling
- */
-asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
-asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
-extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
-
-extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
-
-#ifdef CONFIG_SMP
-static int smp_save_fp_context(struct sigcontext __user *sc)
-{
-       return raw_cpu_has_fpu
-              ? _save_fp_context(sc)
-              : fpu_emulator_save_context(sc);
-}
-
-static int smp_restore_fp_context(struct sigcontext __user *sc)
-{
-       return raw_cpu_has_fpu
-              ? _restore_fp_context(sc)
-              : fpu_emulator_restore_context(sc);
-}
-#endif
-
-static inline void signal_init(void)
-{
-#ifdef CONFIG_SMP
-       /* For now just do the cpu_has_fpu check when the functions are invoked */
-       save_fp_context = smp_save_fp_context;
-       restore_fp_context = smp_restore_fp_context;
-#else
-       if (cpu_has_fpu) {
-               save_fp_context = _save_fp_context;
-               restore_fp_context = _restore_fp_context;
-       } else {
-               save_fp_context = fpu_emulator_save_context;
-               restore_fp_context = fpu_emulator_restore_context;
-       }
-#endif
-}
-
-#ifdef CONFIG_MIPS32_COMPAT
-
-/*
- * This is used by 32-bit signal stuff on the 64-bit kernel
- */
-asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
-asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
-extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
-
-extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
-
-static inline void signal32_init(void)
-{
-       if (cpu_has_fpu) {
-               save_fp_context32 = _save_fp_context32;
-               restore_fp_context32 = _restore_fp_context32;
-       } else {
-               save_fp_context32 = fpu_emulator_save_context32;
-               restore_fp_context32 = fpu_emulator_restore_context32;
-       }
-}
-#endif
-
 extern void cpu_cache_init(void);
 extern void tlb_init(void);
 extern void flush_tlb_handlers(void);
@@ -1751,13 +1708,10 @@ void __init trap_init(void)
        else
                memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80);
 
-       signal_init();
-#ifdef CONFIG_MIPS32_COMPAT
-       signal32_init();
-#endif
-
        local_flush_icache_range(ebase, ebase + 0x400);
        flush_tlb_handlers();
 
        sort_extable(__start___dbe_table, __stop___dbe_table);
+
+       register_cu2_notifier(&default_cu2_notifier);
 }
index 67bd626..69b039c 100644 (file)
@@ -81,6 +81,7 @@
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/byteorder.h>
+#include <asm/cop2.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -451,17 +452,27 @@ static void emulate_load_store_insn(struct pt_regs *regs,
                 */
                goto sigbus;
 
+       /*
+        * COP2 is available to implementor for application specific use.
+        * It's up to applications to register a notifier chain and do
+        * whatever they have to do, including possible sending of signals.
+        */
        case lwc2_op:
+               cu2_notifier_call_chain(CU2_LWC2_OP, regs);
+               break;
+
        case ldc2_op:
+               cu2_notifier_call_chain(CU2_LDC2_OP, regs);
+               break;
+
        case swc2_op:
+               cu2_notifier_call_chain(CU2_SWC2_OP, regs);
+               break;
+
        case sdc2_op:
-               /*
-                * These are the coprocessor 2 load/stores.  The current
-                * implementations don't use cp2 and cp2 should always be
-                * disabled in c0_status.  So send SIGILL.
-                 * (No longer true: The Sony Praystation uses cp2 for
-                 * 3D matrix operations.  Dunno if that thingy has a MMU ...)
-                */
+               cu2_notifier_call_chain(CU2_SDC2_OP, regs);
+               break;
+
        default:
                /*
                 * Pheeee...  We encountered an yet unknown instruction or
index 162b299..f25df73 100644 (file)
@@ -46,6 +46,7 @@ SECTIONS
                SCHED_TEXT
                LOCK_TEXT
                KPROBES_TEXT
+               IRQENTRY_TEXT
                *(.text.*)
                *(.fixup)
                *(.gnu.warning)
index 0bb6037..8e388da 100644 (file)
@@ -4,12 +4,14 @@
  * Brian Murphy <brian.murphy@eicon.com>
  *
  */
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
 
 #include <linux/timer.h>
@@ -38,12 +40,9 @@ static void pvc_display(unsigned long data)
 
 static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
 
-static int pvc_proc_read_line(char *page, char **start,
-                            off_t off, int count,
-                            int *eof, void *data)
+static int pvc_line_proc_show(struct seq_file *m, void *v)
 {
-       char *origpage = page;
-       int lineno = *(int *)data;
+       int lineno = *(int *)m->private;
 
        if (lineno < 0 || lineno > PVC_NLINES) {
                printk(KERN_WARNING "proc_read_line: invalid lineno %d\n", lineno);
@@ -51,45 +50,66 @@ static int pvc_proc_read_line(char *page, char **start,
        }
 
        mutex_lock(&pvc_mutex);
-       page += sprintf(page, "%s\n", pvc_lines[lineno]);
+       seq_printf(m, "%s\n", pvc_lines[lineno]);
        mutex_unlock(&pvc_mutex);
 
-       return page - origpage;
+       return 0;
 }
 
-static int pvc_proc_write_line(struct file *file, const char *buffer,
-                          unsigned long count, void *data)
+static int pvc_line_proc_open(struct inode *inode, struct file *file)
 {
-       int origcount = count;
-       int lineno = *(int *)data;
+       return single_open(file, pvc_line_proc_show, PDE(inode)->data);
+}
 
-       if (lineno < 0 || lineno > PVC_NLINES) {
-               printk(KERN_WARNING "proc_write_line: invalid lineno %d\n",
-                      lineno);
-               return origcount;
-       }
+static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *pos)
+{
+       int lineno = *(int *)PDE(file->f_path.dentry->d_inode)->data;
+       char kbuf[PVC_LINELEN];
+       size_t len;
+
+       BUG_ON(lineno < 0 || lineno > PVC_NLINES);
 
-       if (count > PVC_LINELEN)
-               count = PVC_LINELEN;
+       len = min(count, sizeof(kbuf) - 1);
+       if (copy_from_user(kbuf, buf, len))
+               return -EFAULT;
+       kbuf[len] = '\0';
 
-       if (buffer[count-1] == '\n')
-               count--;
+       if (len > 0 && kbuf[len - 1] == '\n')
+               len--;
 
        mutex_lock(&pvc_mutex);
-       strncpy(pvc_lines[lineno], buffer, count);
-       pvc_lines[lineno][count] = '\0';
+       strncpy(pvc_lines[lineno], kbuf, len);
+       pvc_lines[lineno][len] = '\0';
        mutex_unlock(&pvc_mutex);
 
        tasklet_schedule(&pvc_display_tasklet);
 
-       return origcount;
+       return count;
 }
 
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
-                          unsigned long count, void *data)
+static const struct file_operations pvc_line_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pvc_line_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = pvc_line_proc_write,
+};
+
+static ssize_t pvc_scroll_proc_write(struct file *file, const char __user *buf,
+                                    size_t count, loff_t *pos)
 {
-       int origcount = count;
-       int cmd = simple_strtol(buffer, NULL, 10);
+       char kbuf[42];
+       size_t len;
+       int cmd;
+
+       len = min(count, sizeof(kbuf) - 1);
+       if (copy_from_user(kbuf, buf, len))
+               return -EFAULT;
+       kbuf[len] = '\0';
+
+       cmd = simple_strtol(kbuf, NULL, 10);
 
        mutex_lock(&pvc_mutex);
        if (scroll_interval != 0)
@@ -110,22 +130,31 @@ static int pvc_proc_write_scroll(struct file *file, const char *buffer,
        }
        mutex_unlock(&pvc_mutex);
 
-       return origcount;
+       return count;
 }
 
-static int pvc_proc_read_scroll(char *page, char **start,
-                            off_t off, int count,
-                            int *eof, void *data)
+static int pvc_scroll_proc_show(struct seq_file *m, void *v)
 {
-       char *origpage = page;
-
        mutex_lock(&pvc_mutex);
-       page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
+       seq_printf(m, "%d\n", scroll_dir * scroll_interval);
        mutex_unlock(&pvc_mutex);
 
-       return page - origpage;
+       return 0;
 }
 
+static int pvc_scroll_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pvc_scroll_proc_show, NULL);
+}
+
+static const struct file_operations pvc_scroll_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pvc_scroll_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = pvc_scroll_proc_write,
+};
 
 void pvc_proc_timerfunc(unsigned long data)
 {
@@ -163,22 +192,16 @@ static int __init pvc_proc_init(void)
                pvc_linedata[i] = i;
        }
        for (i = 0; i < PVC_NLINES; i++) {
-               proc_entry = create_proc_entry(pvc_linename[i], 0644,
-                                              pvc_display_dir);
+               proc_entry = proc_create_data(pvc_linename[i], 0644, pvc_display_dir,
+                                       &pvc_line_proc_fops, &pvc_linedata[i]);
                if (proc_entry == NULL)
                        goto error;
-
-               proc_entry->read_proc = pvc_proc_read_line;
-               proc_entry->write_proc = pvc_proc_write_line;
-               proc_entry->data = &pvc_linedata[i];
        }
-       proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
+       proc_entry = proc_create("scroll", 0644, pvc_display_dir,
+                                &pvc_scroll_proc_fops);
        if (proc_entry == NULL)
                goto error;
 
-       proc_entry->write_proc = pvc_proc_write_scroll;
-       proc_entry->read_proc = pvc_proc_read_scroll;
-
        init_timer(&timer);
        timer.function = pvc_proc_timerfunc;
 
index 6acc6cb..20fde19 100644 (file)
@@ -100,8 +100,8 @@ void __init prom_init(void)
 
        /* Get the command line */
        if (argc > 0) {
-               strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
-               arcs_cmdline[CL_SIZE-1] = '\0';
+               strncpy(arcs_cmdline, argv[0], COMMAND_LINE_SIZE-1);
+               arcs_cmdline[COMMAND_LINE_SIZE-1] = '\0';
        }
 
        /* Set the I/O base address */
index 14b9a28..d87ffd0 100644 (file)
@@ -204,7 +204,7 @@ static ctl_table lasat_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_lasat_prid,
-.      },
+       },
 #ifdef CONFIG_INET
        {
                .procname       = "ipaddr",
index d450925..3df1967 100644 (file)
@@ -1,31 +1,85 @@
 choice
-    prompt "Machine Type"
-    depends on MACH_LOONGSON
+       prompt "Machine Type"
+       depends on MACH_LOONGSON
 
 config LEMOTE_FULOONG2E
-    bool "Lemote Fuloong(2e) mini-PC"
-    select ARCH_SPARSEMEM_ENABLE
-    select CEVT_R4K
-    select CSRC_R4K
-    select SYS_HAS_CPU_LOONGSON2E
-    select DMA_NONCOHERENT
-    select BOOT_ELF32
-    select BOARD_SCACHE
-    select HW_HAS_PCI
-    select I8259
-    select ISA
-    select IRQ_CPU
-    select SYS_SUPPORTS_32BIT_KERNEL
-    select SYS_SUPPORTS_64BIT_KERNEL
-    select SYS_SUPPORTS_LITTLE_ENDIAN
-    select SYS_SUPPORTS_HIGHMEM
-    select SYS_HAS_EARLY_PRINTK
-    select GENERIC_HARDIRQS_NO__DO_IRQ
-    select GENERIC_ISA_DMA_SUPPORT_BROKEN
-    select CPU_HAS_WB
-    help
-      Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
-      an FPGA northbridge
-
-      Lemote Fuloong(2e) mini PC have a VIA686B south bridge.
+       bool "Lemote Fuloong(2e) mini-PC"
+       select ARCH_SPARSEMEM_ENABLE
+       select CEVT_R4K
+       select CSRC_R4K
+       select SYS_HAS_CPU_LOONGSON2E
+       select DMA_NONCOHERENT
+       select BOOT_ELF32
+       select BOARD_SCACHE
+       select HW_HAS_PCI
+       select I8259
+       select ISA
+       select IRQ_CPU
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select SYS_HAS_EARLY_PRINTK
+       select GENERIC_HARDIRQS_NO__DO_IRQ
+       select GENERIC_ISA_DMA_SUPPORT_BROKEN
+       select CPU_HAS_WB
+       help
+         Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
+         an FPGA northbridge
+
+         Lemote Fuloong(2e) mini PC have a VIA686B south bridge.
+
+config LEMOTE_MACH2F
+       bool "Lemote Loongson 2F family machines"
+       select ARCH_SPARSEMEM_ENABLE
+       select BOARD_SCACHE
+       select BOOT_ELF32
+       select CEVT_R4K if ! MIPS_EXTERNAL_TIMER
+       select CPU_HAS_WB
+       select CS5536
+       select CSRC_R4K if ! MIPS_EXTERNAL_TIMER
+       select DMA_NONCOHERENT
+       select GENERIC_HARDIRQS_NO__DO_IRQ
+       select GENERIC_ISA_DMA_SUPPORT_BROKEN
+       select HW_HAS_PCI
+       select I8259
+       select IRQ_CPU
+       select ISA
+       select SYS_HAS_CPU_LOONGSON2F
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_HIGHMEM
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       help
+         Lemote Loongson 2F family machines utilize the 2F revision of
+         Loongson processor and the AMD CS5536 south bridge.
+
+         These family machines include fuloong2f mini PC, yeeloong2f notebook,
+         LingLoong allinone PC and so forth.
 endchoice
+
+config CS5536
+       bool
+
+config CS5536_MFGPT
+       bool "CS5536 MFGPT Timer"
+       depends on CS5536
+       select MIPS_EXTERNAL_TIMER
+       help
+         This option enables the mfgpt0 timer of AMD CS5536.
+
+         If you want to enable the Loongson2 CPUFreq Driver, Please enable
+         this option at first, otherwise, You will get wrong system time.
+
+         If unsure, say Yes.
+
+config LOONGSON_SUSPEND
+       bool
+       default y
+       depends on CPU_SUPPORTS_CPUFREQ && SUSPEND
+
+config LOONGSON_UART_BASE
+       bool
+       default y
+       depends on EARLY_PRINTK || SERIAL_8250
index 39048c4..2b76cb0 100644 (file)
@@ -9,3 +9,9 @@ obj-$(CONFIG_MACH_LOONGSON) += common/
 #
 
 obj-$(CONFIG_LEMOTE_FULOONG2E)  += fuloong-2e/
+
+#
+# Lemote loongson2f family machines
+#
+
+obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
index 656b3cc..7668c4d 100644 (file)
@@ -3,9 +3,23 @@
 #
 
 obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
-    pci.o bonito-irq.o mem.o machtype.o
+    pci.o bonito-irq.o mem.o machtype.o platform.o
 
 #
-# Early printk support
+# Serial port support
 #
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_SERIAL_8250) += serial.o
+obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
+
+#
+# Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure
+# space
+#
+obj-$(CONFIG_CS5536) += cs5536/
+
+#
+# Suspend Support
+#
+
+obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
index 3e31e7a..2dc2a4c 100644 (file)
  *  option) any later version.
  */
 #include <linux/interrupt.h>
+#include <linux/compiler.h>
 
 #include <loongson.h>
 
 static inline void bonito_irq_enable(unsigned int irq)
 {
-       BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+       LOONGSON_INTENSET = (1 << (irq - LOONGSON_IRQ_BASE));
        mmiowb();
 }
 
 static inline void bonito_irq_disable(unsigned int irq)
 {
-       BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+       LOONGSON_INTENCLR = (1 << (irq - LOONGSON_IRQ_BASE));
        mmiowb();
 }
 
@@ -35,7 +36,7 @@ static struct irq_chip bonito_irq_type = {
        .unmask = bonito_irq_enable,
 };
 
-static struct irqaction dma_timeout_irqaction = {
+static struct irqaction __maybe_unused dma_timeout_irqaction = {
        .handler        = no_action,
        .name           = "dma_timeout",
 };
@@ -44,8 +45,10 @@ void bonito_irq_init(void)
 {
        u32 i;
 
-       for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++)
+       for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
                set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
 
-       setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+#ifdef CONFIG_CPU_LOONGSON2E
+       setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction);
+#endif
 }
index 75f1b24..7ad47f2 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
  * Author: Fuxin Zhang, zhangfx@lemote.com
  *
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Wu Zhangjin, wuzj@lemote.com
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -49,4 +49,6 @@ void __init prom_init_cmdline(void)
                strcat(arcs_cmdline, " console=ttyS0,115200");
        if ((strstr(arcs_cmdline, "root=")) == NULL)
                strcat(arcs_cmdline, " root=/dev/hda1");
+
+       prom_init_machtype();
 }
diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile
new file mode 100644 (file)
index 0000000..510d4cd
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for CS5536 support.
+#
+
+obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \
+                       cs5536_isa.o cs5536_ehci.o
+
+#
+# Enable cs5536 mfgpt Timer
+#
+obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/loongson/common/cs5536/cs5536_acc.c b/arch/mips/loongson/common/cs5536/cs5536_acc.c
new file mode 100644 (file)
index 0000000..b49485f
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * the ACC Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_acc_write_reg(int reg, u32 value)
+{
+       u32 hi = 0, lo = value;
+
+       switch (reg) {
+       case PCI_COMMAND:
+               _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+               if (value & PCI_COMMAND_MASTER)
+                       lo |= (0x03 << 8);
+               else
+                       lo &= ~(0x03 << 8);
+               _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+               break;
+       case PCI_STATUS:
+               if (value & PCI_STATUS_PARITY) {
+                       _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+                       if (lo & SB_PARE_ERR_FLAG) {
+                               lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+                               _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+                       }
+               }
+               break;
+       case PCI_BAR0_REG:
+               if (value == PCI_BAR_RANGE_MASK) {
+                       _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+                       lo |= SOFT_BAR_ACC_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else if (value & 0x01) {
+                       value &= 0xfffffffc;
+                       hi = 0xA0000000 | ((value & 0x000ff000) >> 12);
+                       lo = 0x000fff80 | ((value & 0x00000fff) << 20);
+                       _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM1), hi, lo);
+               }
+               break;
+       case PCI_ACC_INT_REG:
+               _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+               /* disable all the usb interrupt in PIC */
+               lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT);
+               if (value)      /* enable all the acc interrupt in PIC */
+                       lo |= (CS5536_ACC_INTR << PIC_YSEL_LOW_ACC_SHIFT);
+               _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+               break;
+       default:
+               break;
+       }
+}
+
+u32 pci_acc_read_reg(int reg)
+{
+       u32 hi, lo;
+       u32 conf_data = 0;
+
+       switch (reg) {
+       case PCI_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID, CS5536_VENDOR_ID);
+               break;
+       case PCI_COMMAND:
+               _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+               if (((lo & 0xfff00000) || (hi & 0x000000ff))
+                   && ((hi & 0xf0000000) == 0xa0000000))
+                       conf_data |= PCI_COMMAND_IO;
+               _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+               if ((lo & 0x300) == 0x300)
+                       conf_data |= PCI_COMMAND_MASTER;
+               break;
+       case PCI_STATUS:
+               conf_data |= PCI_STATUS_66MHZ;
+               conf_data |= PCI_STATUS_FAST_BACK;
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               if (lo & SB_PARE_ERR_FLAG)
+                       conf_data |= PCI_STATUS_PARITY;
+               conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+               break;
+       case PCI_CLASS_REVISION:
+               _rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo);
+               conf_data = lo & 0x000000ff;
+               conf_data |= (CS5536_ACC_CLASS_CODE << 8);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               conf_data =
+                   CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+                                           PCI_NORMAL_LATENCY_TIMER);
+               break;
+       case PCI_BAR0_REG:
+               _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+               if (lo & SOFT_BAR_ACC_FLAG) {
+                       conf_data = CS5536_ACC_RANGE |
+                           PCI_BASE_ADDRESS_SPACE_IO;
+                       lo &= ~SOFT_BAR_ACC_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else {
+                       _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+                       conf_data = (hi & 0x000000ff) << 12;
+                       conf_data |= (lo & 0xfff00000) >> 20;
+                       conf_data |= 0x01;
+                       conf_data &= ~0x02;
+               }
+               break;
+       case PCI_CARDBUS_CIS:
+               conf_data = PCI_CARDBUS_CIS_POINTER;
+               break;
+       case PCI_SUBSYSTEM_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID, CS5536_SUB_VENDOR_ID);
+               break;
+       case PCI_ROM_ADDRESS:
+               conf_data = PCI_EXPANSION_ROM_BAR;
+               break;
+       case PCI_CAPABILITY_LIST:
+               conf_data = PCI_CAPLIST_USB_POINTER;
+               break;
+       case PCI_INTERRUPT_LINE:
+               conf_data =
+                   CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR);
+               break;
+       default:
+               break;
+       }
+
+       return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
new file mode 100644 (file)
index 0000000..74f9c59
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * the EHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ehci_write_reg(int reg, u32 value)
+{
+       u32 hi = 0, lo = value;
+
+       switch (reg) {
+       case PCI_COMMAND:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               if (value & PCI_COMMAND_MASTER)
+                       hi |= PCI_COMMAND_MASTER;
+               else
+                       hi &= ~PCI_COMMAND_MASTER;
+
+               if (value & PCI_COMMAND_MEMORY)
+                       hi |= PCI_COMMAND_MEMORY;
+               else
+                       hi &= ~PCI_COMMAND_MEMORY;
+               _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+               break;
+       case PCI_STATUS:
+               if (value & PCI_STATUS_PARITY) {
+                       _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+                       if (lo & SB_PARE_ERR_FLAG) {
+                               lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+                               _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+                       }
+               }
+               break;
+       case PCI_BAR0_REG:
+               if (value == PCI_BAR_RANGE_MASK) {
+                       _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+                       lo |= SOFT_BAR_EHCI_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else if ((value & 0x01) == 0x00) {
+                       _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+
+                       value &= 0xfffffff0;
+                       hi = 0x40000000 | ((value & 0xff000000) >> 24);
+                       lo = 0x000fffff | ((value & 0x00fff000) << 8);
+                       _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM4), hi, lo);
+               }
+               break;
+       case PCI_EHCI_LEGSMIEN_REG:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               hi &= 0x003f0000;
+               hi |= (value & 0x3f) << 16;
+               _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+               break;
+       case PCI_EHCI_FLADJ_REG:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               hi &= ~0x00003f00;
+               hi |= value & 0x00003f00;
+               _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+               break;
+       default:
+               break;
+       }
+}
+
+u32 pci_ehci_read_reg(int reg)
+{
+       u32 conf_data = 0;
+       u32 hi, lo;
+
+       switch (reg) {
+       case PCI_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID, CS5536_VENDOR_ID);
+               break;
+       case PCI_COMMAND:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               if (hi & PCI_COMMAND_MASTER)
+                       conf_data |= PCI_COMMAND_MASTER;
+               if (hi & PCI_COMMAND_MEMORY)
+                       conf_data |= PCI_COMMAND_MEMORY;
+               break;
+       case PCI_STATUS:
+               conf_data |= PCI_STATUS_66MHZ;
+               conf_data |= PCI_STATUS_FAST_BACK;
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               if (lo & SB_PARE_ERR_FLAG)
+                       conf_data |= PCI_STATUS_PARITY;
+               conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+               break;
+       case PCI_CLASS_REVISION:
+               _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+               conf_data = lo & 0x000000ff;
+               conf_data |= (CS5536_EHCI_CLASS_CODE << 8);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               conf_data =
+                   CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+                                           PCI_NORMAL_LATENCY_TIMER);
+               break;
+       case PCI_BAR0_REG:
+               _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+               if (lo & SOFT_BAR_EHCI_FLAG) {
+                       conf_data = CS5536_EHCI_RANGE |
+                           PCI_BASE_ADDRESS_SPACE_MEMORY;
+                       lo &= ~SOFT_BAR_EHCI_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else {
+                       _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+                       conf_data = lo & 0xfffff000;
+               }
+               break;
+       case PCI_CARDBUS_CIS:
+               conf_data = PCI_CARDBUS_CIS_POINTER;
+               break;
+       case PCI_SUBSYSTEM_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+               break;
+       case PCI_ROM_ADDRESS:
+               conf_data = PCI_EXPANSION_ROM_BAR;
+               break;
+       case PCI_CAPABILITY_LIST:
+               conf_data = PCI_CAPLIST_USB_POINTER;
+               break;
+       case PCI_INTERRUPT_LINE:
+               conf_data =
+                   CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+               break;
+       case PCI_EHCI_LEGSMIEN_REG:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               conf_data = (hi & 0x003f0000) >> 16;
+               break;
+       case PCI_EHCI_LEGSMISTS_REG:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               conf_data = (hi & 0x3f000000) >> 24;
+               break;
+       case PCI_EHCI_FLADJ_REG:
+               _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+               conf_data = hi & 0x00003f00;
+               break;
+       default:
+               break;
+       }
+
+       return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c
new file mode 100644 (file)
index 0000000..3f61594
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * the IDE Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ide_write_reg(int reg, u32 value)
+{
+       u32 hi = 0, lo = value;
+
+       switch (reg) {
+       case PCI_COMMAND:
+               _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+               if (value & PCI_COMMAND_MASTER)
+                       lo |= (0x03 << 4);
+               else
+                       lo &= ~(0x03 << 4);
+               _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+               break;
+       case PCI_STATUS:
+               if (value & PCI_STATUS_PARITY) {
+                       _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+                       if (lo & SB_PARE_ERR_FLAG) {
+                               lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+                               _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+                       }
+               }
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               value &= 0x0000ff00;
+               _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+               hi &= 0xffffff00;
+               hi |= (value >> 8);
+               _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+               break;
+       case PCI_BAR4_REG:
+               if (value == PCI_BAR_RANGE_MASK) {
+                       _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+                       lo |= SOFT_BAR_IDE_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else if (value & 0x01) {
+                       lo = (value & 0xfffffff0) | 0x1;
+                       _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo);
+
+                       value &= 0xfffffffc;
+                       hi = 0x60000000 | ((value & 0x000ff000) >> 12);
+                       lo = 0x000ffff0 | ((value & 0x00000fff) << 20);
+                       _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM2), hi, lo);
+               }
+               break;
+       case PCI_IDE_CFG_REG:
+               if (value == CS5536_IDE_FLASH_SIGNATURE) {
+                       _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+                       lo |= 0x01;
+                       _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
+               } else
+                       _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
+               break;
+       case PCI_IDE_DTC_REG:
+               _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
+               break;
+       case PCI_IDE_CAST_REG:
+               _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
+               break;
+       case PCI_IDE_ETC_REG:
+               _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
+               break;
+       case PCI_IDE_PM_REG:
+               _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
+               break;
+       default:
+               break;
+       }
+}
+
+u32 pci_ide_read_reg(int reg)
+{
+       u32 conf_data = 0;
+       u32 hi, lo;
+
+       switch (reg) {
+       case PCI_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID, CS5536_VENDOR_ID);
+               break;
+       case PCI_COMMAND:
+               _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+               if (lo & 0xfffffff0)
+                       conf_data |= PCI_COMMAND_IO;
+               _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+               if ((lo & 0x30) == 0x30)
+                       conf_data |= PCI_COMMAND_MASTER;
+               break;
+       case PCI_STATUS:
+               conf_data |= PCI_STATUS_66MHZ;
+               conf_data |= PCI_STATUS_FAST_BACK;
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               if (lo & SB_PARE_ERR_FLAG)
+                       conf_data |= PCI_STATUS_PARITY;
+               conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+               break;
+       case PCI_CLASS_REVISION:
+               _rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo);
+               conf_data = lo & 0x000000ff;
+               conf_data |= (CS5536_IDE_CLASS_CODE << 8);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+               hi &= 0x000000f8;
+               conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi);
+               break;
+       case PCI_BAR4_REG:
+               _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+               if (lo & SOFT_BAR_IDE_FLAG) {
+                       conf_data = CS5536_IDE_RANGE |
+                           PCI_BASE_ADDRESS_SPACE_IO;
+                       lo &= ~SOFT_BAR_IDE_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else {
+                       _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+                       conf_data = lo & 0xfffffff0;
+                       conf_data |= 0x01;
+                       conf_data &= ~0x02;
+               }
+               break;
+       case PCI_CARDBUS_CIS:
+               conf_data = PCI_CARDBUS_CIS_POINTER;
+               break;
+       case PCI_SUBSYSTEM_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID, CS5536_SUB_VENDOR_ID);
+               break;
+       case PCI_ROM_ADDRESS:
+               conf_data = PCI_EXPANSION_ROM_BAR;
+               break;
+       case PCI_CAPABILITY_LIST:
+               conf_data = PCI_CAPLIST_POINTER;
+               break;
+       case PCI_INTERRUPT_LINE:
+               conf_data =
+                   CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_IDE_INTR);
+               break;
+       case PCI_IDE_CFG_REG:
+               _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
+               conf_data = lo;
+               break;
+       case PCI_IDE_DTC_REG:
+               _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
+               conf_data = lo;
+               break;
+       case PCI_IDE_CAST_REG:
+               _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
+               conf_data = lo;
+               break;
+       case PCI_IDE_ETC_REG:
+               _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
+               conf_data = lo;
+       case PCI_IDE_PM_REG:
+               _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
+               conf_data = lo;
+               break;
+       default:
+               break;
+       }
+
+       return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c
new file mode 100644 (file)
index 0000000..b6f17f5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * the ISA Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* common variables for PCI_ISA_READ/WRITE_BAR */
+static const u32 divil_msr_reg[6] = {
+       DIVIL_MSR_REG(DIVIL_LBAR_SMB), DIVIL_MSR_REG(DIVIL_LBAR_GPIO),
+       DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), DIVIL_MSR_REG(DIVIL_LBAR_IRQ),
+       DIVIL_MSR_REG(DIVIL_LBAR_PMS), DIVIL_MSR_REG(DIVIL_LBAR_ACPI),
+};
+
+static const u32 soft_bar_flag[6] = {
+       SOFT_BAR_SMB_FLAG, SOFT_BAR_GPIO_FLAG, SOFT_BAR_MFGPT_FLAG,
+       SOFT_BAR_IRQ_FLAG, SOFT_BAR_PMS_FLAG, SOFT_BAR_ACPI_FLAG,
+};
+
+static const u32 sb_msr_reg[6] = {
+       SB_MSR_REG(SB_R0), SB_MSR_REG(SB_R1), SB_MSR_REG(SB_R2),
+       SB_MSR_REG(SB_R3), SB_MSR_REG(SB_R4), SB_MSR_REG(SB_R5),
+};
+
+static const u32 bar_space_range[6] = {
+       CS5536_SMB_RANGE, CS5536_GPIO_RANGE, CS5536_MFGPT_RANGE,
+       CS5536_IRQ_RANGE, CS5536_PMS_RANGE, CS5536_ACPI_RANGE,
+};
+
+static const int bar_space_len[6] = {
+       CS5536_SMB_LENGTH, CS5536_GPIO_LENGTH, CS5536_MFGPT_LENGTH,
+       CS5536_IRQ_LENGTH, CS5536_PMS_LENGTH, CS5536_ACPI_LENGTH,
+};
+
+/*
+ * enable the divil module bar space.
+ *
+ * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg
+ * and the RCONFx(0~5) reg to use the modules.
+ */
+static void divil_lbar_enable(void)
+{
+       u32 hi, lo;
+       int offset;
+
+       /*
+        * The DIVIL IRQ is not used yet. and make the RCONF0 reserved.
+        */
+
+       for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+               _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+               hi |= 0x01;
+               _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+       }
+}
+
+/*
+ * disable the divil module bar space.
+ */
+static void divil_lbar_disable(void)
+{
+       u32 hi, lo;
+       int offset;
+
+       for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+               _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+               hi &= ~0x01;
+               _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+       }
+}
+
+/*
+ * BAR write: write value to the n BAR
+ */
+
+void pci_isa_write_bar(int n, u32 value)
+{
+       u32 hi = 0, lo = value;
+
+       if (value == PCI_BAR_RANGE_MASK) {
+               _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+               lo |= soft_bar_flag[n];
+               _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+       } else if (value & 0x01) {
+               /* NATIVE reg */
+               hi = 0x0000f001;
+               lo &= bar_space_range[n];
+               _wrmsr(divil_msr_reg[n], hi, lo);
+
+               /* RCONFx is 4bytes in units for I/O space */
+               hi = ((value & 0x000ffffc) << 12) |
+                   ((bar_space_len[n] - 4) << 12) | 0x01;
+               lo = ((value & 0x000ffffc) << 12) | 0x01;
+               _wrmsr(sb_msr_reg[n], hi, lo);
+       }
+}
+
+/*
+ * BAR read: read the n BAR
+ */
+
+u32 pci_isa_read_bar(int n)
+{
+       u32 conf_data = 0;
+       u32 hi, lo;
+
+       _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+       if (lo & soft_bar_flag[n]) {
+               conf_data = bar_space_range[n] | PCI_BASE_ADDRESS_SPACE_IO;
+               lo &= ~soft_bar_flag[n];
+               _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+       } else {
+               _rdmsr(divil_msr_reg[n], &hi, &lo);
+               conf_data = lo & bar_space_range[n];
+               conf_data |= 0x01;
+               conf_data &= ~0x02;
+       }
+       return conf_data;
+}
+
+/*
+ * isa_write: ISA write transfer
+ *
+ * We assume that this is not a bus master transfer.
+ */
+void pci_isa_write_reg(int reg, u32 value)
+{
+       u32 hi = 0, lo = value;
+       u32 temp;
+
+       switch (reg) {
+       case PCI_COMMAND:
+               if (value & PCI_COMMAND_IO)
+                       divil_lbar_enable();
+               else
+                       divil_lbar_disable();
+               break;
+       case PCI_STATUS:
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               temp = lo & 0x0000ffff;
+               if ((value & PCI_STATUS_SIG_TARGET_ABORT) &&
+                   (lo & SB_TAS_ERR_EN))
+                       temp |= SB_TAS_ERR_FLAG;
+
+               if ((value & PCI_STATUS_REC_TARGET_ABORT) &&
+                   (lo & SB_TAR_ERR_EN))
+                       temp |= SB_TAR_ERR_FLAG;
+
+               if ((value & PCI_STATUS_REC_MASTER_ABORT)
+                   && (lo & SB_MAR_ERR_EN))
+                       temp |= SB_MAR_ERR_FLAG;
+
+               if ((value & PCI_STATUS_DETECTED_PARITY)
+                   && (lo & SB_PARE_ERR_EN))
+                       temp |= SB_PARE_ERR_FLAG;
+
+               lo = temp;
+               _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               value &= 0x0000ff00;
+               _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+               hi &= 0xffffff00;
+               hi |= (value >> 8);
+               _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+               break;
+       case PCI_BAR0_REG:
+               pci_isa_write_bar(0, value);
+               break;
+       case PCI_BAR1_REG:
+               pci_isa_write_bar(1, value);
+               break;
+       case PCI_BAR2_REG:
+               pci_isa_write_bar(2, value);
+               break;
+       case PCI_BAR3_REG:
+               pci_isa_write_bar(3, value);
+               break;
+       case PCI_BAR4_REG:
+               pci_isa_write_bar(4, value);
+               break;
+       case PCI_BAR5_REG:
+               pci_isa_write_bar(5, value);
+               break;
+       case PCI_UART1_INT_REG:
+               _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+               /* disable uart1 interrupt in PIC */
+               lo &= ~(0xf << 24);
+               if (value)      /* enable uart1 interrupt in PIC */
+                       lo |= (CS5536_UART1_INTR << 24);
+               _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+               break;
+       case PCI_UART2_INT_REG:
+               _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+               /* disable uart2 interrupt in PIC */
+               lo &= ~(0xf << 28);
+               if (value)      /* enable uart2 interrupt in PIC */
+                       lo |= (CS5536_UART2_INTR << 28);
+               _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+               break;
+       case PCI_ISA_FIXUP_REG:
+               if (value) {
+                       /* enable the TARGET ABORT/MASTER ABORT etc. */
+                       _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+                       lo |= 0x00000063;
+                       _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+               }
+
+       default:
+               /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */
+               break;
+       }
+}
+
+/*
+ * isa_read: ISA read transfers
+ *
+ * We assume that this is not a bus master transfer.
+ */
+u32 pci_isa_read_reg(int reg)
+{
+       u32 conf_data = 0;
+       u32 hi, lo;
+
+       switch (reg) {
+       case PCI_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID, CS5536_VENDOR_ID);
+               break;
+       case PCI_COMMAND:
+               /* we just check the first LBAR for the IO enable bit, */
+               /* maybe we should changed later. */
+               _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo);
+               if (hi & 0x01)
+                       conf_data |= PCI_COMMAND_IO;
+               break;
+       case PCI_STATUS:
+               conf_data |= PCI_STATUS_66MHZ;
+               conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+               conf_data |= PCI_STATUS_FAST_BACK;
+
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               if (lo & SB_TAS_ERR_FLAG)
+                       conf_data |= PCI_STATUS_SIG_TARGET_ABORT;
+               if (lo & SB_TAR_ERR_FLAG)
+                       conf_data |= PCI_STATUS_REC_TARGET_ABORT;
+               if (lo & SB_MAR_ERR_FLAG)
+                       conf_data |= PCI_STATUS_REC_MASTER_ABORT;
+               if (lo & SB_PARE_ERR_FLAG)
+                       conf_data |= PCI_STATUS_DETECTED_PARITY;
+               break;
+       case PCI_CLASS_REVISION:
+               _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo);
+               conf_data = lo & 0x000000ff;
+               conf_data |= (CS5536_ISA_CLASS_CODE << 8);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+               hi &= 0x000000f8;
+               conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE, hi);
+               break;
+               /*
+                * we only use the LBAR of DIVIL, no RCONF used.
+                * all of them are IO space.
+                */
+       case PCI_BAR0_REG:
+               return pci_isa_read_bar(0);
+               break;
+       case PCI_BAR1_REG:
+               return pci_isa_read_bar(1);
+               break;
+       case PCI_BAR2_REG:
+               return pci_isa_read_bar(2);
+               break;
+       case PCI_BAR3_REG:
+               break;
+       case PCI_BAR4_REG:
+               return pci_isa_read_bar(4);
+               break;
+       case PCI_BAR5_REG:
+               return pci_isa_read_bar(5);
+               break;
+       case PCI_CARDBUS_CIS:
+               conf_data = PCI_CARDBUS_CIS_POINTER;
+               break;
+       case PCI_SUBSYSTEM_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID, CS5536_SUB_VENDOR_ID);
+               break;
+       case PCI_ROM_ADDRESS:
+               conf_data = PCI_EXPANSION_ROM_BAR;
+               break;
+       case PCI_CAPABILITY_LIST:
+               conf_data = PCI_CAPLIST_POINTER;
+               break;
+       case PCI_INTERRUPT_LINE:
+               /* no interrupt used here */
+               conf_data = CFG_PCI_INTERRUPT_LINE(0x00, 0x00);
+               break;
+       default:
+               break;
+       }
+
+       return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
new file mode 100644 (file)
index 0000000..6cb44db
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * CS5536 General timer functions
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.com
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu zhangjin, wuzj@lemote.com
+ *
+ * Reference: AMD Geode(TM) CS5536 Companion Device Data Book
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+
+#include <asm/time.h>
+
+#include <cs5536/cs5536_mfgpt.h>
+
+DEFINE_SPINLOCK(mfgpt_lock);
+EXPORT_SYMBOL(mfgpt_lock);
+
+static u32 mfgpt_base;
+
+/*
+ * Initialize the MFGPT timer.
+ *
+ * This is also called after resume to bring the MFGPT into operation again.
+ */
+
+/* disable counter */
+void disable_mfgpt0_counter(void)
+{
+       outw(inw(MFGPT0_SETUP) & 0x7fff, MFGPT0_SETUP);
+}
+EXPORT_SYMBOL(disable_mfgpt0_counter);
+
+/* enable counter, comparator2 to event mode, 14.318MHz clock */
+void enable_mfgpt0_counter(void)
+{
+       outw(0xe310, MFGPT0_SETUP);
+}
+EXPORT_SYMBOL(enable_mfgpt0_counter);
+
+static void init_mfgpt_timer(enum clock_event_mode mode,
+                            struct clock_event_device *evt)
+{
+       spin_lock(&mfgpt_lock);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               outw(COMPARE, MFGPT0_CMP2);     /* set comparator2 */
+               outw(0, MFGPT0_CNT);    /* set counter to 0 */
+               enable_mfgpt0_counter();
+               break;
+
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
+                   evt->mode == CLOCK_EVT_MODE_ONESHOT)
+                       disable_mfgpt0_counter();
+               break;
+
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* The oneshot mode have very high deviation, Not use it! */
+               break;
+
+       case CLOCK_EVT_MODE_RESUME:
+               /* Nothing to do here */
+               break;
+       }
+       spin_unlock(&mfgpt_lock);
+}
+
+static struct clock_event_device mfgpt_clockevent = {
+       .name = "mfgpt",
+       .features = CLOCK_EVT_FEAT_PERIODIC,
+       .set_mode = init_mfgpt_timer,
+       .irq = CS5536_MFGPT_INTR,
+};
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       u32 basehi;
+
+       /*
+        * get MFGPT base address
+        *
+        * NOTE: do not remove me, it's need for the value of mfgpt_base is
+        * variable
+        */
+       _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base);
+
+       /* ack */
+       outw(inw(MFGPT0_SETUP) | 0x4000, MFGPT0_SETUP);
+
+       mfgpt_clockevent.event_handler(&mfgpt_clockevent);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction irq5 = {
+       .handler = timer_interrupt,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
+       .name = "timer"
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init setup_mfgpt0_timer(void)
+{
+       u32 basehi;
+       struct clock_event_device *cd = &mfgpt_clockevent;
+       unsigned int cpu = smp_processor_id();
+
+       cd->cpumask = cpumask_of(cpu);
+       clockevent_set_clock(cd, MFGPT_TICK_RATE);
+       cd->max_delta_ns = clockevent_delta2ns(0xffff, cd);
+       cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
+
+       /* Enable MFGPT0 Comparator 2 Output to the Interrupt Mapper */
+       _wrmsr(DIVIL_MSR_REG(MFGPT_IRQ), 0, 0x100);
+
+       /* Enable Interrupt Gate 5 */
+       _wrmsr(DIVIL_MSR_REG(PIC_ZSEL_LOW), 0, 0x50000);
+
+       /* get MFGPT base address */
+       _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base);
+
+       clockevents_register_device(cd);
+
+       setup_irq(CS5536_MFGPT_INTR, &irq5);
+}
+
+/*
+ * Since the MFGPT overflows every tick, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static cycle_t mfgpt_read(struct clocksource *cs)
+{
+       unsigned long flags;
+       int count;
+       u32 jifs;
+       static int old_count;
+       static u32 old_jifs;
+
+       spin_lock_irqsave(&mfgpt_lock, flags);
+       /*
+        * Although our caller may have the read side of xtime_lock,
+        * this is now a seqlock, and we are cheating in this routine
+        * by having side effects on state that we cannot undo if
+        * there is a collision on the seqlock and our caller has to
+        * retry.  (Namely, old_jifs and old_count.)  So we must treat
+        * jiffies as volatile despite the lock.  We read jiffies
+        * before latching the timer count to guarantee that although
+        * the jiffies value might be older than the count (that is,
+        * the counter may underflow between the last point where
+        * jiffies was incremented and the point where we latch the
+        * count), it cannot be newer.
+        */
+       jifs = jiffies;
+       /* read the count */
+       count = inw(MFGPT0_CNT);
+
+       /*
+        * It's possible for count to appear to go the wrong way for this
+        * reason:
+        *
+        *  The timer counter underflows, but we haven't handled the resulting
+        *  interrupt and incremented jiffies yet.
+        *
+        * Previous attempts to handle these cases intelligently were buggy, so
+        * we just do the simple thing now.
+        */
+       if (count < old_count && jifs == old_jifs)
+               count = old_count;
+
+       old_count = count;
+       old_jifs = jifs;
+
+       spin_unlock_irqrestore(&mfgpt_lock, flags);
+
+       return (cycle_t) (jifs * COMPARE) + count;
+}
+
+static struct clocksource clocksource_mfgpt = {
+       .name = "mfgpt",
+       .rating = 120, /* Functional for real use, but not desired */
+       .read = mfgpt_read,
+       .mask = CLOCKSOURCE_MASK(32),
+       .mult = 0,
+       .shift = 22,
+};
+
+int __init init_mfgpt_clocksource(void)
+{
+       if (num_possible_cpus() > 1)    /* MFGPT does not scale! */
+               return 0;
+
+       clocksource_mfgpt.mult = clocksource_hz2mult(MFGPT_TICK_RATE, 22);
+       return clocksource_register(&clocksource_mfgpt);
+}
+
+arch_initcall(init_mfgpt_clocksource);
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
new file mode 100644 (file)
index 0000000..8fdb02b
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * the OHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ohci_write_reg(int reg, u32 value)
+{
+       u32 hi = 0, lo = value;
+
+       switch (reg) {
+       case PCI_COMMAND:
+               _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+               if (value & PCI_COMMAND_MASTER)
+                       hi |= PCI_COMMAND_MASTER;
+               else
+                       hi &= ~PCI_COMMAND_MASTER;
+
+               if (value & PCI_COMMAND_MEMORY)
+                       hi |= PCI_COMMAND_MEMORY;
+               else
+                       hi &= ~PCI_COMMAND_MEMORY;
+               _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+               break;
+       case PCI_STATUS:
+               if (value & PCI_STATUS_PARITY) {
+                       _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+                       if (lo & SB_PARE_ERR_FLAG) {
+                               lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+                               _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+                       }
+               }
+               break;
+       case PCI_BAR0_REG:
+               if (value == PCI_BAR_RANGE_MASK) {
+                       _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+                       lo |= SOFT_BAR_OHCI_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else if ((value & 0x01) == 0x00) {
+                       _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+
+                       value &= 0xfffffff0;
+                       hi = 0x40000000 | ((value & 0xff000000) >> 24);
+                       lo = 0x000fffff | ((value & 0x00fff000) << 8);
+                       _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM3), hi, lo);
+               }
+               break;
+       case PCI_OHCI_INT_REG:
+               _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+               lo &= ~(0xf << PIC_YSEL_LOW_USB_SHIFT);
+               if (value)      /* enable all the usb interrupt in PIC */
+                       lo |= (CS5536_USB_INTR << PIC_YSEL_LOW_USB_SHIFT);
+               _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+               break;
+       default:
+               break;
+       }
+}
+
+u32 pci_ohci_read_reg(int reg)
+{
+       u32 conf_data = 0;
+       u32 hi, lo;
+
+       switch (reg) {
+       case PCI_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID);
+               break;
+       case PCI_COMMAND:
+               _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+               if (hi & PCI_COMMAND_MASTER)
+                       conf_data |= PCI_COMMAND_MASTER;
+               if (hi & PCI_COMMAND_MEMORY)
+                       conf_data |= PCI_COMMAND_MEMORY;
+               break;
+       case PCI_STATUS:
+               conf_data |= PCI_STATUS_66MHZ;
+               conf_data |= PCI_STATUS_FAST_BACK;
+               _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+               if (lo & SB_PARE_ERR_FLAG)
+                       conf_data |= PCI_STATUS_PARITY;
+               conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+               break;
+       case PCI_CLASS_REVISION:
+               _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+               conf_data = lo & 0x000000ff;
+               conf_data |= (CS5536_OHCI_CLASS_CODE << 8);
+               break;
+       case PCI_CACHE_LINE_SIZE:
+               conf_data =
+                   CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+                                           PCI_NORMAL_LATENCY_TIMER);
+               break;
+       case PCI_BAR0_REG:
+               _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+               if (lo & SOFT_BAR_OHCI_FLAG) {
+                       conf_data = CS5536_OHCI_RANGE |
+                           PCI_BASE_ADDRESS_SPACE_MEMORY;
+                       lo &= ~SOFT_BAR_OHCI_FLAG;
+                       _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+               } else {
+                       _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+                       conf_data = lo & 0xffffff00;
+                       conf_data &= ~0x0000000f;       /* 32bit mem */
+               }
+               break;
+       case PCI_CARDBUS_CIS:
+               conf_data = PCI_CARDBUS_CIS_POINTER;
+               break;
+       case PCI_SUBSYSTEM_VENDOR_ID:
+               conf_data =
+                   CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+               break;
+       case PCI_ROM_ADDRESS:
+               conf_data = PCI_EXPANSION_ROM_BAR;
+               break;
+       case PCI_CAPABILITY_LIST:
+               conf_data = PCI_CAPLIST_USB_POINTER;
+               break;
+       case PCI_INTERRUPT_LINE:
+               conf_data =
+                   CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+               break;
+       case PCI_OHCI_INT_REG:
+               _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+               if ((lo & 0x00000f00) == CS5536_USB_INTR)
+                       conf_data = 1;
+               break;
+       default:
+               break;
+       }
+
+       return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson/common/cs5536/cs5536_pci.c
new file mode 100644 (file)
index 0000000..e23f3d7
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * read/write operation to the PCI config space of CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *     the Virtual Support Module(VSM) for virtulizing the PCI
+ *     configure space are defined in cs5536_modulename.c respectively,
+ *
+ *     after this virtulizing, user can access the PCI configure space
+ *     directly as a normal multi-function PCI device which follows
+ *     the PCI-2.2 spec.
+ */
+
+#include <linux/types.h>
+#include <cs5536/cs5536_vsm.h>
+
+enum {
+       CS5536_FUNC_START = -1,
+       CS5536_ISA_FUNC,
+       reserved_func,
+       CS5536_IDE_FUNC,
+       CS5536_ACC_FUNC,
+       CS5536_OHCI_FUNC,
+       CS5536_EHCI_FUNC,
+       CS5536_FUNC_END,
+};
+
+static const cs5536_pci_vsm_write vsm_conf_write[] = {
+       [CS5536_ISA_FUNC]       pci_isa_write_reg,
+       [reserved_func]         NULL,
+       [CS5536_IDE_FUNC]       pci_ide_write_reg,
+       [CS5536_ACC_FUNC]       pci_acc_write_reg,
+       [CS5536_OHCI_FUNC]      pci_ohci_write_reg,
+       [CS5536_EHCI_FUNC]      pci_ehci_write_reg,
+};
+
+static const cs5536_pci_vsm_read vsm_conf_read[] = {
+       [CS5536_ISA_FUNC]       pci_isa_read_reg,
+       [reserved_func]         NULL,
+       [CS5536_IDE_FUNC]       pci_ide_read_reg,
+       [CS5536_ACC_FUNC]       pci_acc_read_reg,
+       [CS5536_OHCI_FUNC]      pci_ohci_read_reg,
+       [CS5536_EHCI_FUNC]      pci_ehci_read_reg,
+};
+
+/*
+ * write to PCI config space and transfer it to MSR write.
+ */
+void cs5536_pci_conf_write4(int function, int reg, u32 value)
+{
+       if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+               return;
+       if ((reg < 0) || (reg > 0x100) || ((reg & 0x03) != 0))
+               return;
+
+       if (vsm_conf_write[function] != NULL)
+               vsm_conf_write[function](reg, value);
+}
+
+/*
+ * read PCI config space and transfer it to MSR access.
+ */
+u32 cs5536_pci_conf_read4(int function, int reg)
+{
+       u32 data = 0;
+
+       if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+               return 0;
+       if ((reg < 0) || ((reg & 0x03) != 0))
+               return 0;
+       if (reg > 0x100)
+               return 0xffffffff;
+
+       if (vsm_conf_read[function] != NULL)
+               data = vsm_conf_read[function](reg);
+
+       return data;
+}
index bc73edc..23e7a8f 100644 (file)
@@ -1,7 +1,7 @@
 /*  early printk support
  *
  *  Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
- *  Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ *  Copyright (c) 2009 Lemote Inc.
  *  Author: Wu Zhangjin, wuzj@lemote.com
  *
  *  This program is free software; you can redistribute  it and/or modify it
 #include <linux/serial_reg.h>
 
 #include <loongson.h>
-#include <machine.h>
 
 #define PORT(base, offset) (u8 *)(base + offset)
 
-static inline unsigned int serial_in(phys_addr_t base, int offset)
+static inline unsigned int serial_in(unsigned char *base, int offset)
 {
        return readb(PORT(base, offset));
 }
 
-static inline void serial_out(phys_addr_t base, int offset, int value)
+static inline void serial_out(unsigned char *base, int offset, int value)
 {
        writeb(value, PORT(base, offset));
 }
 
 void prom_putchar(char c)
 {
-       phys_addr_t uart_base =
-               (phys_addr_t) ioremap_nocache(LOONGSON_UART_BASE, 8);
+       int timeout;
+       unsigned char *uart_base;
 
-       while ((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0)
+       uart_base = (unsigned char *)_loongson_uart_base;
+       timeout = 1024;
+
+       while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) &&
+                       (timeout-- > 0))
                ;
 
        serial_out(uart_base, UART_TX, c);
index b9ef503..196d947 100644 (file)
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+#include <linux/module.h>
+
 #include <asm/bootinfo.h>
 
 #include <loongson.h>
 
 unsigned long bus_clock, cpu_clock_freq;
+EXPORT_SYMBOL(cpu_clock_freq);
 unsigned long memsize, highmemsize;
 
 /* pmon passes arguments in 32bit pointers */
index 3abe927..a2abd93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Wu Zhangjin, wuzj@lemote.com
  *
  * This program is free software; you can redistribute  it and/or modify it
 
 #include <linux/bootmem.h>
 
-#include <asm/bootinfo.h>
-
 #include <loongson.h>
 
+/* Loongson CPU address windows config space base address */
+unsigned long __maybe_unused _loongson_addrwincfg_base;
+
 void __init prom_init(void)
 {
-    /* init base address of io space */
+       /* init base address of io space */
        set_io_port_base((unsigned long)
-               ioremap(BONITO_PCIIO_BASE, BONITO_PCIIO_SIZE));
+               ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+       _loongson_addrwincfg_base = (unsigned long)
+               ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
+#endif
 
        prom_init_cmdline();
        prom_init_env();
        prom_init_memory();
+
+       /*init the uart base address */
+       prom_init_uart_base();
 }
 
 void __init prom_free_prom_memory(void)
index b32b4a3..20e7328 100644 (file)
@@ -20,21 +20,21 @@ void bonito_irqdispatch(void)
        int i;
 
        /* workaround the IO dma problem: let cpu looping to allow DMA finish */
-       int_status = BONITO_INTISR;
+       int_status = LOONGSON_INTISR;
        if (int_status & (1 << 10)) {
                while (int_status & (1 << 10)) {
                        udelay(1);
-                       int_status = BONITO_INTISR;
+                       int_status = LOONGSON_INTISR;
                }
        }
 
        /* Get pending sources, masked by current enables */
-       int_status = BONITO_INTISR & BONITO_INTEN;
+       int_status = LOONGSON_INTISR & LOONGSON_INTEN;
 
        if (int_status != 0) {
                i = __ffs(int_status);
                int_status &= ~(1 << i);
-               do_IRQ(BONITO_IRQ_BASE + i);
+               do_IRQ(LOONGSON_IRQ_BASE + i);
        }
 }
 
@@ -60,13 +60,13 @@ void __init arch_init_irq(void)
        set_irq_trigger_mode();
 
        /* no steer */
-       BONITO_INTSTEER = 0;
+       LOONGSON_INTSTEER = 0;
 
        /*
         * Mask out all interrupt by writing "1" to all bit position in
         * the interrupt reset reg.
         */
-       BONITO_INTENCLR = ~0;
+       LOONGSON_INTENCLR = ~0;
 
        /* machine specific irq init */
        mach_init_irq();
index 7b34824..0ed52b3 100644 (file)
@@ -15,6 +15,9 @@
 #include <loongson.h>
 #include <machine.h>
 
+/* please ensure the length of the machtype string is less than 50 */
+#define MACHTYPE_LEN 50
+
 static const char *system_types[] = {
        [MACH_LOONGSON_UNKNOWN]         "unknown loongson machine",
        [MACH_LEMOTE_FL2E]              "lemote-fuloong-2e-box",
@@ -22,29 +25,35 @@ static const char *system_types[] = {
        [MACH_LEMOTE_ML2F7]             "lemote-mengloong-2f-7inches",
        [MACH_LEMOTE_YL2F89]            "lemote-yeeloong-2f-8.9inches",
        [MACH_DEXXON_GDIUM2F10]         "dexxon-gidum-2f-10inches",
+       [MACH_LEMOTE_NAS]               "lemote-nas-2f",
+       [MACH_LEMOTE_LL2F]              "lemote-lynloong-2f",
        [MACH_LOONGSON_END]             NULL,
 };
 
 const char *get_system_type(void)
 {
-       if (mips_machtype == MACH_UNKNOWN)
-               mips_machtype = LOONGSON_MACHTYPE;
-
        return system_types[mips_machtype];
 }
 
-static __init int machtype_setup(char *str)
+void __init prom_init_machtype(void)
 {
+       char *p, str[MACHTYPE_LEN];
        int machtype = MACH_LEMOTE_FL2E;
 
-       if (!str)
-               return -EINVAL;
+       mips_machtype = LOONGSON_MACHTYPE;
+
+       p = strstr(arcs_cmdline, "machtype=");
+       if (!p)
+               return;
+       p += strlen("machtype=");
+       strncpy(str, p, MACHTYPE_LEN);
+       p = strstr(str, " ");
+       if (p)
+               *p = '\0';
 
        for (; system_types[machtype]; machtype++)
                if (strstr(system_types[machtype], str)) {
                        mips_machtype = machtype;
                        break;
                }
-       return 0;
 }
-__setup("machtype=", machtype_setup);
index e94ef15..ceacd09 100644 (file)
 
 #include <loongson.h>
 #include <mem.h>
+#include <pci.h>
 
 void __init prom_init_memory(void)
 {
     add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+
+    add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize <<
+                           20), BOOT_MEM_RESERVED);
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+       {
+               int bit;
+
+               bit = fls(memsize + highmemsize);
+               if (bit != ffs(memsize + highmemsize))
+                       bit += 20;
+               else
+                       bit = bit + 20 - 1;
+
+               /* set cpu window3 to map CPU to DDR: 2G -> 2G */
+               LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul,
+                                         0x80000000ul, (1 << bit));
+               mmiowb();
+       }
+#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
+
 #ifdef CONFIG_64BIT
-    if (highmemsize > 0)
-       add_memory_region(LOONGSON_HIGHMEM_START,
-               highmemsize << 20, BOOT_MEM_RAM);
-#endif /* CONFIG_64BIT */
+       if (highmemsize > 0)
+               add_memory_region(LOONGSON_HIGHMEM_START,
+                                 highmemsize << 20, BOOT_MEM_RAM);
+
+       add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
+                         LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
+
+#endif /* !CONFIG_64BIT */
 }
 
 /* override of arch/mips/mm/cache.c: __uncached_access */
@@ -33,3 +58,61 @@ int __uncached_access(struct file *file, unsigned long addr)
                ((addr >= LOONGSON_MMIO_MEM_START) &&
                 (addr < LOONGSON_MMIO_MEM_END));
 }
+
+#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
+
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+
+static unsigned long uca_start, uca_end;
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                             unsigned long size, pgprot_t vma_prot)
+{
+       unsigned long offset = pfn << PAGE_SHIFT;
+       unsigned long end = offset + size;
+
+       if (__uncached_access(file, offset)) {
+               if (((uca_start && offset) >= uca_start) &&
+                   (end <= uca_end))
+                       return __pgprot((pgprot_val(vma_prot) &
+                                        ~_CACHE_MASK) |
+                                       _CACHE_UNCACHED_ACCELERATED);
+               else
+                       return pgprot_noncached(vma_prot);
+       }
+       return vma_prot;
+}
+
+static int __init find_vga_mem_init(void)
+{
+       struct pci_dev *dev = 0;
+       struct resource *r;
+       int idx;
+
+       if (uca_start)
+               return 0;
+
+       for_each_pci_dev(dev) {
+               if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+                       for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+                               r = &dev->resource[idx];
+                               if (!r->start && r->end)
+                                       continue;
+                               if (r->flags & IORESOURCE_IO)
+                                       continue;
+                               if (r->flags & IORESOURCE_MEM) {
+                                       uca_start = r->start;
+                                       uca_end = r->end;
+                                       return 0;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+late_initcall(find_vga_mem_init);
+#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */
index a3a4abf..31d8c5e 100644 (file)
@@ -27,7 +27,7 @@ static struct resource loongson_pci_io_resource = {
 };
 
 static struct pci_controller  loongson_pci_controller = {
-       .pci_ops        = &bonito64_pci_ops,
+       .pci_ops        = &loongson_pci_ops,
        .io_resource    = &loongson_pci_io_resource,
        .mem_resource   = &loongson_pci_mem_resource,
        .mem_offset     = 0x00000000UL,
@@ -44,15 +44,15 @@ static void __init setup_pcimap(void)
         * pcimap: PCI_MAP2  PCI_Mem_Lo2 PCI_Mem_Lo1 PCI_Mem_Lo0
         *           [<2G]   [384M,448M] [320M,384M] [0M,64M]
         */
-       BONITO_PCIMAP = BONITO_PCIMAP_PCIMAP_2 |
-               BONITO_PCIMAP_WIN(2, BONITO_PCILO2_BASE) |
-               BONITO_PCIMAP_WIN(1, BONITO_PCILO1_BASE) |
-               BONITO_PCIMAP_WIN(0, 0);
+       LOONGSON_PCIMAP = LOONGSON_PCIMAP_PCIMAP_2 |
+               LOONGSON_PCIMAP_WIN(2, LOONGSON_PCILO2_BASE) |
+               LOONGSON_PCIMAP_WIN(1, LOONGSON_PCILO1_BASE) |
+               LOONGSON_PCIMAP_WIN(0, 0);
 
        /*
         * PCI-DMA to local mapping: [2G,2G+256M] -> [0M,256M]
         */
-       BONITO_PCIBASE0 = 0x80000000ul;   /* base: 2G -> mmap: 0M */
+       LOONGSON_PCIBASE0 = 0x80000000ul;   /* base: 2G -> mmap: 0M */
        /* size: 256M, burst transmission, pre-fetch enable, 64bit */
        LOONGSON_PCI_HIT0_SEL_L = 0xc000000cul;
        LOONGSON_PCI_HIT0_SEL_H = 0xfffffffful;
@@ -67,6 +67,14 @@ static void __init setup_pcimap(void)
        /* can not change gnt to break pci transfer when device's gnt not
        deassert for some broken device */
        LOONGSON_PXARB_CFG = 0x00fe0105ul;
+
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+       /*
+        * set cpu addr window2 to map CPU address space to PCI address space
+        */
+       LOONGSON_ADDRWIN_CPUTOPCI(ADDRWIN_WIN2, LOONGSON_CPU_MEM_SRC,
+               LOONGSON_PCI_MEM_DST, MMAP_CPUTOPCI_SIZE);
+#endif
 }
 
 static int __init pcibios_init(void)
diff --git a/arch/mips/loongson/common/platform.c b/arch/mips/loongson/common/platform.c
new file mode 100644 (file)
index 0000000..be81777
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+static struct platform_device loongson2_cpufreq_device = {
+       .name = "loongson2_cpufreq",
+       .id = -1,
+};
+
+static int __init loongson2_cpufreq_init(void)
+{
+       struct cpuinfo_mips *c = &current_cpu_data;
+
+       /* Only 2F revision and it's successors support CPUFreq */
+       if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON2F)
+               return platform_device_register(&loongson2_cpufreq_device);
+
+       return -ENODEV;
+}
+
+arch_initcall(loongson2_cpufreq_init);
diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c
new file mode 100644 (file)
index 0000000..b625fec
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * loongson-specific suspend support
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+#include <loongson.h>
+
+static unsigned int __maybe_unused cached_master_mask; /* i8259A */
+static unsigned int __maybe_unused cached_slave_mask;
+static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */
+
+void arch_suspend_disable_irqs(void)
+{
+       /* disable all mips events */
+       local_irq_disable();
+
+#ifdef CONFIG_I8259
+       /* disable all events of i8259A */
+       cached_slave_mask = inb(PIC_SLAVE_IMR);
+       cached_master_mask = inb(PIC_MASTER_IMR);
+
+       outb(0xff, PIC_SLAVE_IMR);
+       inb(PIC_SLAVE_IMR);
+       outb(0xff, PIC_MASTER_IMR);
+       inb(PIC_MASTER_IMR);
+#endif
+       /* disable all events of bonito */
+       cached_bonito_irq_mask = LOONGSON_INTEN;
+       LOONGSON_INTENCLR = 0xffff;
+       (void)LOONGSON_INTENCLR;
+}
+
+void arch_suspend_enable_irqs(void)
+{
+       /* enable all mips events */
+       local_irq_enable();
+#ifdef CONFIG_I8259
+       /* only enable the cached events of i8259A */
+       outb(cached_slave_mask, PIC_SLAVE_IMR);
+       outb(cached_master_mask, PIC_MASTER_IMR);
+#endif
+       /* enable all cached events of bonito */
+       LOONGSON_INTENSET = cached_bonito_irq_mask;
+       (void)LOONGSON_INTENSET;
+}
+
+/*
+ * Setup the board-specific events for waking up loongson from wait mode
+ */
+void __weak setup_wakeup_events(void)
+{
+}
+
+/*
+ * Check wakeup events
+ */
+int __weak wakeup_loongson(void)
+{
+       return 1;
+}
+
+/*
+ * If the events are really what we want to wakeup the CPU, wake it up
+ * otherwise put the CPU asleep again.
+ */
+static void wait_for_wakeup_events(void)
+{
+       while (!wakeup_loongson())
+               LOONGSON_CHIPCFG0 &= ~0x7;
+}
+
+/*
+ * Stop all perf counters
+ *
+ * $24 is the control register of Loongson perf counter
+ */
+static inline void stop_perf_counters(void)
+{
+       __write_64bit_c0_register($24, 0, 0);
+}
+
+
+static void loongson_suspend_enter(void)
+{
+       static unsigned int cached_cpu_freq;
+
+       /* setup wakeup events via enabling the IRQs */
+       setup_wakeup_events();
+
+       stop_perf_counters();
+
+       cached_cpu_freq = LOONGSON_CHIPCFG0;
+
+       /* Put CPU into wait mode */
+       LOONGSON_CHIPCFG0 &= ~0x7;
+
+       /* wait for the given events to wakeup cpu from wait mode */
+       wait_for_wakeup_events();
+
+       LOONGSON_CHIPCFG0 = cached_cpu_freq;
+       mmiowb();
+}
+
+void __weak mach_suspend(void)
+{
+}
+
+void __weak mach_resume(void)
+{
+}
+
+static int loongson_pm_enter(suspend_state_t state)
+{
+       mach_suspend();
+
+       /* processor specific suspend */
+       loongson_suspend_enter();
+
+       mach_resume();
+
+       return 0;
+}
+
+static int loongson_pm_valid_state(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_ON:
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
+static struct platform_suspend_ops loongson_pm_ops = {
+       .valid  = loongson_pm_valid_state,
+       .enter  = loongson_pm_enter,
+};
+
+static int __init loongson_pm_init(void)
+{
+       suspend_set_ops(&loongson_pm_ops);
+
+       return 0;
+}
+arch_initcall(loongson_pm_init);
index 97e9182..d57f171 100644 (file)
@@ -22,7 +22,7 @@ static void loongson_restart(char *command)
        mach_prepare_reboot();
 
        /* reboot via jumping to boot base address */
-       ((void (*)(void))ioremap_nocache(BONITO_BOOT_BASE, 4)) ();
+       ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) ();
 }
 
 static void loongson_halt(void)
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
new file mode 100644 (file)
index 0000000..23b66a5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Yan hua (yanhua@lemote.com)
+ * Author: Wu Zhangjin (wuzj@lemote.com)
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+#include <machine.h>
+
+#define PORT(int)                      \
+{                                                              \
+       .irq            = int,                                  \
+       .uartclk        = 1843200,                              \
+       .iotype         = UPIO_PORT,                            \
+       .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,    \
+       .regshift       = 0,                                    \
+}
+
+#define PORT_M(int)                            \
+{                                                              \
+       .irq            = MIPS_CPU_IRQ_BASE + (int),            \
+       .uartclk        = 3686400,                              \
+       .iotype         = UPIO_MEM,                             \
+       .membase        = (void __iomem *)NULL,                 \
+       .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,    \
+       .regshift       = 0,                                    \
+}
+
+static struct plat_serial8250_port uart8250_data[][2] = {
+       [MACH_LOONGSON_UNKNOWN]         {},
+       [MACH_LEMOTE_FL2E]              {PORT(4), {} },
+       [MACH_LEMOTE_FL2F]              {PORT(3), {} },
+       [MACH_LEMOTE_ML2F7]             {PORT_M(3), {} },
+       [MACH_LEMOTE_YL2F89]            {PORT_M(3), {} },
+       [MACH_DEXXON_GDIUM2F10]         {PORT_M(3), {} },
+       [MACH_LEMOTE_NAS]               {PORT_M(3), {} },
+       [MACH_LEMOTE_LL2F]              {PORT(3), {} },
+       [MACH_LOONGSON_END]             {},
+};
+
+static struct platform_device uart8250_device = {
+       .name = "serial8250",
+       .id = PLAT8250_DEV_PLATFORM,
+};
+
+static int __init serial_init(void)
+{
+       unsigned char iotype;
+
+       iotype = uart8250_data[mips_machtype][0].iotype;
+
+       if (UPIO_MEM == iotype)
+               uart8250_data[mips_machtype][0].membase =
+                       (void __iomem *)_loongson_uart_base;
+       else if (UPIO_PORT == iotype)
+               uart8250_data[mips_machtype][0].iobase =
+                   loongson_uart_base - LOONGSON_PCIIO_BASE;
+
+       uart8250_device.dev.platform_data = uart8250_data[mips_machtype];
+
+       return platform_device_register(&uart8250_device);
+}
+
+device_initcall(serial_init);
index 6e08c82..35f0b66 100644 (file)
 #include <asm/time.h>
 
 #include <loongson.h>
+#include <cs5536/cs5536_mfgpt.h>
 
 void __init plat_time_init(void)
 {
        /* setup mips r4k timer */
        mips_hpt_frequency = cpu_clock_freq / 2;
+
+       setup_mfgpt0_timer();
 }
 
 void read_persistent_clock(struct timespec *ts)
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
new file mode 100644 (file)
index 0000000..78ff66a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+/* ioremapped */
+unsigned long _loongson_uart_base;
+EXPORT_SYMBOL(_loongson_uart_base);
+/* raw */
+unsigned long loongson_uart_base;
+EXPORT_SYMBOL(loongson_uart_base);
+
+void prom_init_loongson_uart_base(void)
+{
+       switch (mips_machtype) {
+       case MACH_LEMOTE_FL2E:
+               loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8;
+               break;
+       case MACH_LEMOTE_FL2F:
+       case MACH_LEMOTE_LL2F:
+               loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8;
+               break;
+       case MACH_LEMOTE_ML2F7:
+       case MACH_LEMOTE_YL2F89:
+       case MACH_DEXXON_GDIUM2F10:
+       case MACH_LEMOTE_NAS:
+       default:
+               /* The CPU provided serial port */
+               loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
+               break;
+       }
+
+       _loongson_uart_base =
+               (unsigned long)ioremap_nocache(loongson_uart_base, 8);
+}
index 7888cf6..320e937 100644 (file)
@@ -47,8 +47,8 @@ static struct irqaction cascade_irqaction = {
 void __init set_irq_trigger_mode(void)
 {
        /* most bonito irq should be level triggered */
-       BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
-           BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+       LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR |
+           LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES;
 }
 
 void __init mach_init_irq(void)
index 677fe18..fc16c67 100644 (file)
@@ -14,8 +14,8 @@
 
 void mach_prepare_reboot(void)
 {
-       BONITO_BONGENCFG &= ~(1 << 2);
-       BONITO_BONGENCFG |= (1 << 2);
+       LOONGSON_GENCFG &= ~(1 << 2);
+       LOONGSON_GENCFG |= (1 << 2);
 }
 
 void mach_prepare_shutdown(void)
diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile
new file mode 100644 (file)
index 0000000..4d84b27
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for lemote loongson2f family machines
+#
+
+obj-y += irq.o reset.o ec_kb3310b.o
+
+#
+# Suspend Support
+#
+
+obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
new file mode 100644 (file)
index 0000000..4d84111
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Basic KB3310B Embedded Controller support for the YeeLoong 2F netbook
+ *
+ *  Copyright (C) 2008 Lemote Inc.
+ *  Author: liujl <liujl@lemote.com>, 2008-04-20
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include "ec_kb3310b.h"
+
+static DEFINE_SPINLOCK(index_access_lock);
+static DEFINE_SPINLOCK(port_access_lock);
+
+unsigned char ec_read(unsigned short addr)
+{
+       unsigned char value;
+       unsigned long flags;
+
+       spin_lock_irqsave(&index_access_lock, flags);
+       outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
+       outb((addr & 0x00ff), EC_IO_PORT_LOW);
+       value = inb(EC_IO_PORT_DATA);
+       spin_unlock_irqrestore(&index_access_lock, flags);
+
+       return value;
+}
+EXPORT_SYMBOL_GPL(ec_read);
+
+void ec_write(unsigned short addr, unsigned char val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&index_access_lock, flags);
+       outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
+       outb((addr & 0x00ff), EC_IO_PORT_LOW);
+       outb(val, EC_IO_PORT_DATA);
+       /*  flush the write action */
+       inb(EC_IO_PORT_DATA);
+       spin_unlock_irqrestore(&index_access_lock, flags);
+
+       return;
+}
+EXPORT_SYMBOL_GPL(ec_write);
+
+/*
+ * This function is used for EC command writes and corresponding status queries.
+ */
+int ec_query_seq(unsigned char cmd)
+{
+       int timeout;
+       unsigned char status;
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&port_access_lock, flags);
+
+       /* make chip goto reset mode */
+       udelay(EC_REG_DELAY);
+       outb(cmd, EC_CMD_PORT);
+       udelay(EC_REG_DELAY);
+
+       /* check if the command is received by ec */
+       timeout = EC_CMD_TIMEOUT;
+       status = inb(EC_STS_PORT);
+       while (timeout-- && (status & (1 << 1))) {
+               status = inb(EC_STS_PORT);
+               udelay(EC_REG_DELAY);
+       }
+
+       if (timeout <= 0) {
+               printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
+               ret = -EINVAL;
+       } else
+               printk(KERN_INFO
+                          "(%x/%d)ec issued command %d status : 0x%x\n",
+                          timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
+
+       spin_unlock_irqrestore(&port_access_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ec_query_seq);
+
+/*
+ * Send query command to EC to get the proper event number
+ */
+int ec_query_event_num(void)
+{
+       return ec_query_seq(CMD_GET_EVENT_NUM);
+}
+EXPORT_SYMBOL(ec_query_event_num);
+
+/*
+ * Get event number from EC
+ *
+ * NOTE: This routine must follow the query_event_num function in the
+ * interrupt.
+ */
+int ec_get_event_num(void)
+{
+       int timeout = 100;
+       unsigned char value;
+       unsigned char status;
+
+       udelay(EC_REG_DELAY);
+       status = inb(EC_STS_PORT);
+       udelay(EC_REG_DELAY);
+       while (timeout-- && !(status & (1 << 0))) {
+               status = inb(EC_STS_PORT);
+               udelay(EC_REG_DELAY);
+       }
+       if (timeout <= 0) {
+               pr_info("%s: get event number timeout.\n", __func__);
+
+               return -EINVAL;
+       }
+       value = inb(EC_DAT_PORT);
+       udelay(EC_REG_DELAY);
+
+       return value;
+}
+EXPORT_SYMBOL(ec_get_event_num);
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.h b/arch/mips/loongson/lemote-2f/ec_kb3310b.h
new file mode 100644 (file)
index 0000000..1595a21
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * KB3310B Embedded Controller
+ *
+ *  Copyright (C) 2008 Lemote Inc.
+ *  Author: liujl <liujl@lemote.com>, 2008-03-14
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _EC_KB3310B_H
+#define _EC_KB3310B_H
+
+extern unsigned char ec_read(unsigned short addr);
+extern void ec_write(unsigned short addr, unsigned char val);
+extern int ec_query_seq(unsigned char cmd);
+extern int ec_query_event_num(void);
+extern int ec_get_event_num(void);
+
+typedef int (*sci_handler) (int status);
+extern sci_handler yeeloong_report_lid_status;
+
+#define SCI_IRQ_NUM 0x0A
+
+/*
+ * The following registers are determined by the EC index configuration.
+ * 1, fill the PORT_HIGH as EC register high part.
+ * 2, fill the PORT_LOW as EC register low part.
+ * 3, fill the PORT_DATA as EC register write data or get the data from it.
+ */
+#define        EC_IO_PORT_HIGH 0x0381
+#define        EC_IO_PORT_LOW  0x0382
+#define        EC_IO_PORT_DATA 0x0383
+
+/*
+ * EC delay time is 500us for register and status access
+ */
+#define        EC_REG_DELAY    500     /* unit : us */
+#define        EC_CMD_TIMEOUT  0x1000
+
+/*
+ * EC access port for SCI communication
+ */
+#define        EC_CMD_PORT             0x66
+#define        EC_STS_PORT             0x66
+#define        EC_DAT_PORT             0x62
+#define        CMD_INIT_IDLE_MODE      0xdd
+#define        CMD_EXIT_IDLE_MODE      0xdf
+#define        CMD_INIT_RESET_MODE     0xd8
+#define        CMD_REBOOT_SYSTEM       0x8c
+#define        CMD_GET_EVENT_NUM       0x84
+#define        CMD_PROGRAM_PIECE       0xda
+
+/* temperature & fan registers */
+#define        REG_TEMPERATURE_VALUE   0xF458
+#define        REG_FAN_AUTO_MAN_SWITCH 0xF459
+#define        BIT_FAN_AUTO            0
+#define        BIT_FAN_MANUAL          1
+#define        REG_FAN_CONTROL         0xF4D2
+#define        BIT_FAN_CONTROL_ON      (1 << 0)
+#define        BIT_FAN_CONTROL_OFF     (0 << 0)
+#define        REG_FAN_STATUS          0xF4DA
+#define        BIT_FAN_STATUS_ON       (1 << 0)
+#define        BIT_FAN_STATUS_OFF      (0 << 0)
+#define        REG_FAN_SPEED_HIGH      0xFE22
+#define        REG_FAN_SPEED_LOW       0xFE23
+#define        REG_FAN_SPEED_LEVEL     0xF4CC
+/* fan speed divider */
+#define        FAN_SPEED_DIVIDER       480000  /* (60*1000*1000/62.5/2)*/
+
+/* battery registers */
+#define        REG_BAT_DESIGN_CAP_HIGH         0xF77D
+#define        REG_BAT_DESIGN_CAP_LOW          0xF77E
+#define        REG_BAT_FULLCHG_CAP_HIGH        0xF780
+#define        REG_BAT_FULLCHG_CAP_LOW         0xF781
+#define        REG_BAT_DESIGN_VOL_HIGH         0xF782
+#define        REG_BAT_DESIGN_VOL_LOW          0xF783
+#define        REG_BAT_CURRENT_HIGH            0xF784
+#define        REG_BAT_CURRENT_LOW             0xF785
+#define        REG_BAT_VOLTAGE_HIGH            0xF786
+#define        REG_BAT_VOLTAGE_LOW             0xF787
+#define        REG_BAT_TEMPERATURE_HIGH        0xF788
+#define        REG_BAT_TEMPERATURE_LOW         0xF789
+#define        REG_BAT_RELATIVE_CAP_HIGH       0xF492
+#define        REG_BAT_RELATIVE_CAP_LOW        0xF493
+#define        REG_BAT_VENDOR                  0xF4C4
+#define        FLAG_BAT_VENDOR_SANYO           0x01
+#define        FLAG_BAT_VENDOR_SIMPLO          0x02
+#define        REG_BAT_CELL_COUNT              0xF4C6
+#define        FLAG_BAT_CELL_3S1P              0x03
+#define        FLAG_BAT_CELL_3S2P              0x06
+#define        REG_BAT_CHARGE                  0xF4A2
+#define        FLAG_BAT_CHARGE_DISCHARGE       0x01
+#define        FLAG_BAT_CHARGE_CHARGE          0x02
+#define        FLAG_BAT_CHARGE_ACPOWER         0x00
+#define        REG_BAT_STATUS                  0xF4B0
+#define        BIT_BAT_STATUS_LOW              (1 << 5)
+#define        BIT_BAT_STATUS_DESTROY          (1 << 2)
+#define        BIT_BAT_STATUS_FULL             (1 << 1)
+#define        BIT_BAT_STATUS_IN               (1 << 0)
+#define        REG_BAT_CHARGE_STATUS           0xF4B1
+#define        BIT_BAT_CHARGE_STATUS_OVERTEMP  (1 << 2)
+#define        BIT_BAT_CHARGE_STATUS_PRECHG    (1 << 1)
+#define        REG_BAT_STATE                   0xF482
+#define        BIT_BAT_STATE_CHARGING          (1 << 1)
+#define        BIT_BAT_STATE_DISCHARGING       (1 << 0)
+#define        REG_BAT_POWER                   0xF440
+#define        BIT_BAT_POWER_S3                (1 << 2)
+#define        BIT_BAT_POWER_ON                (1 << 1)
+#define        BIT_BAT_POWER_ACIN              (1 << 0)
+
+/* other registers */
+/* Audio: rd/wr */
+#define        REG_AUDIO_VOLUME        0xF46C
+#define        REG_AUDIO_MUTE          0xF4E7
+#define        REG_AUDIO_BEEP          0xF4D0
+/* USB port power or not: rd/wr */
+#define        REG_USB0_FLAG           0xF461
+#define        REG_USB1_FLAG           0xF462
+#define        REG_USB2_FLAG           0xF463
+#define        BIT_USB_FLAG_ON         1
+#define        BIT_USB_FLAG_OFF        0
+/* LID */
+#define        REG_LID_DETECT          0xF4BD
+#define        BIT_LID_DETECT_ON       1
+#define        BIT_LID_DETECT_OFF      0
+/* CRT */
+#define        REG_CRT_DETECT          0xF4AD
+#define        BIT_CRT_DETECT_PLUG     1
+#define        BIT_CRT_DETECT_UNPLUG   0
+/* LCD backlight brightness adjust: 9 levels */
+#define        REG_DISPLAY_BRIGHTNESS  0xF4F5
+/* Black screen Status */
+#define        BIT_DISPLAY_LCD_ON      1
+#define        BIT_DISPLAY_LCD_OFF     0
+/* LCD backlight control: off/restore */
+#define        REG_BACKLIGHT_CTRL      0xF7BD
+#define        BIT_BACKLIGHT_ON        1
+#define        BIT_BACKLIGHT_OFF       0
+/* Reset the machine auto-clear: rd/wr */
+#define        REG_RESET               0xF4EC
+#define        BIT_RESET_ON            1
+/* Light the led: rd/wr */
+#define        REG_LED                 0xF4C8
+#define        BIT_LED_RED_POWER       (1 << 0)
+#define        BIT_LED_ORANGE_POWER    (1 << 1)
+#define        BIT_LED_GREEN_CHARGE    (1 << 2)
+#define        BIT_LED_RED_CHARGE      (1 << 3)
+#define        BIT_LED_NUMLOCK         (1 << 4)
+/* Test led mode, all led on/off */
+#define        REG_LED_TEST            0xF4C2
+#define        BIT_LED_TEST_IN         1
+#define        BIT_LED_TEST_OUT        0
+/* Camera on/off */
+#define        REG_CAMERA_STATUS       0xF46A
+#define        BIT_CAMERA_STATUS_ON    1
+#define        BIT_CAMERA_STATUS_OFF   0
+#define        REG_CAMERA_CONTROL      0xF7B7
+#define        BIT_CAMERA_CONTROL_OFF  0
+#define        BIT_CAMERA_CONTROL_ON   1
+/* Wlan Status */
+#define        REG_WLAN                0xF4FA
+#define        BIT_WLAN_ON             1
+#define        BIT_WLAN_OFF            0
+#define        REG_DISPLAY_LCD         0xF79F
+
+/* SCI Event Number from EC */
+enum {
+       EVENT_LID = 0x23,       /*  LID open/close */
+       EVENT_DISPLAY_TOGGLE,   /*  Fn+F3 for display switch */
+       EVENT_SLEEP,            /*  Fn+F1 for entering sleep mode */
+       EVENT_OVERTEMP,         /*  Over-temperature happened */
+       EVENT_CRT_DETECT,       /*  CRT is connected */
+       EVENT_CAMERA,           /*  Camera on/off */
+       EVENT_USB_OC2,          /*  USB2 Over Current occurred */
+       EVENT_USB_OC0,          /*  USB0 Over Current occurred */
+       EVENT_BLACK_SCREEN,     /*  Turn on/off backlight */
+       EVENT_AUDIO_MUTE,       /*  Mute on/off */
+       EVENT_DISPLAY_BRIGHTNESS,/* LCD backlight brightness adjust */
+       EVENT_AC_BAT,           /*  AC & Battery relative issue */
+       EVENT_AUDIO_VOLUME,     /*  Volume adjust */
+       EVENT_WLAN,             /*  Wlan on/off */
+       EVENT_END
+};
+
+#endif /* !_EC_KB3310B_H */
diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c
new file mode 100644 (file)
index 0000000..77d32f9
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 Lemote Inc.
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+#include <loongson.h>
+#include <machine.h>
+
+#define LOONGSON_TIMER_IRQ     (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */
+#define LOONGSON_PERFCNT_IRQ   (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
+#define LOONGSON_NORTH_BRIDGE_IRQ      (MIPS_CPU_IRQ_BASE + 6) /* bonito */
+#define LOONGSON_UART_IRQ      (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */
+#define LOONGSON_SOUTH_BRIDGE_IRQ      (MIPS_CPU_IRQ_BASE + 2) /* i8259 */
+
+#define LOONGSON_INT_BIT_INT0          (1 << 11)
+#define LOONGSON_INT_BIT_INT1          (1 << 12)
+
+/*
+ * The generic i8259_irq() make the kernel hang on booting.  Since we cannot
+ * get the irq via the IRR directly, we access the ISR instead.
+ */
+int mach_i8259_irq(void)
+{
+       int irq, isr;
+
+       irq = -1;
+
+       if ((LOONGSON_INTISR & LOONGSON_INTEN) & LOONGSON_INT_BIT_INT0) {
+               spin_lock(&i8259A_lock);
+               isr = inb(PIC_MASTER_CMD) &
+                       ~inb(PIC_MASTER_IMR) & ~(1 << PIC_CASCADE_IR);
+               if (!isr)
+                       isr = (inb(PIC_SLAVE_CMD) & ~inb(PIC_SLAVE_IMR)) << 8;
+               irq = ffs(isr) - 1;
+               if (unlikely(irq == 7)) {
+                       /*
+                        * This may be a spurious interrupt.
+                        *
+                        * Read the interrupt status register (ISR). If the most
+                        * significant bit is not set then there is no valid
+                        * interrupt.
+                        */
+                       outb(0x0B, PIC_MASTER_ISR);     /* ISR register */
+                       if (~inb(PIC_MASTER_ISR) & 0x80)
+                               irq = -1;
+               }
+               spin_unlock(&i8259A_lock);
+       }
+
+       return irq;
+}
+EXPORT_SYMBOL(mach_i8259_irq);
+
+static void i8259_irqdispatch(void)
+{
+       int irq;
+
+       irq = mach_i8259_irq();
+       if (irq >= 0)
+               do_IRQ(irq);
+       else
+               spurious_interrupt();
+}
+
+void mach_irq_dispatch(unsigned int pending)
+{
+       if (pending & CAUSEF_IP7)
+               do_IRQ(LOONGSON_TIMER_IRQ);
+       else if (pending & CAUSEF_IP6) {        /* North Bridge, Perf counter */
+#ifdef CONFIG_OPROFILE
+               do_IRQ(LOONGSON2_PERFCNT_IRQ);
+#endif
+               bonito_irqdispatch();
+       } else if (pending & CAUSEF_IP3)        /* CPU UART */
+               do_IRQ(LOONGSON_UART_IRQ);
+       else if (pending & CAUSEF_IP2)  /* South Bridge */
+               i8259_irqdispatch();
+       else
+               spurious_interrupt();
+}
+
+void __init set_irq_trigger_mode(void)
+{
+       /* setup cs5536 as high level trigger */
+       LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1;
+       LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1);
+}
+
+static irqreturn_t ip6_action(int cpl, void *dev_id)
+{
+       return IRQ_HANDLED;
+}
+
+struct irqaction ip6_irqaction = {
+       .handler = ip6_action,
+       .name = "cascade",
+       .flags = IRQF_SHARED,
+};
+
+struct irqaction cascade_irqaction = {
+       .handler = no_action,
+       .name = "cascade",
+};
+
+void __init mach_init_irq(void)
+{
+       /* init all controller
+        *   0-15         ------> i8259 interrupt
+        *   16-23        ------> mips cpu interrupt
+        *   32-63        ------> bonito irq
+        */
+
+       /* Sets the first-level interrupt dispatcher. */
+       mips_cpu_irq_init();
+       init_i8259_irqs();
+       bonito_irq_init();
+
+       /* setup north bridge irq (bonito) */
+       setup_irq(LOONGSON_NORTH_BRIDGE_IRQ, &ip6_irqaction);
+       /* setup source bridge irq (i8259) */
+       setup_irq(LOONGSON_SOUTH_BRIDGE_IRQ, &cascade_irqaction);
+}
diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c
new file mode 100644 (file)
index 0000000..d7af2e6
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *  Lemote loongson2f family machines' specific suspend support
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/i8042.h>
+#include <linux/module.h>
+
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+#include <cs5536/cs5536_mfgpt.h>
+#include "ec_kb3310b.h"
+
+#define I8042_KBD_IRQ          1
+#define I8042_CTR_KBDINT       0x01
+#define I8042_CTR_KBDDIS       0x10
+
+static unsigned char i8042_ctr;
+
+static int i8042_enable_kbd_port(void)
+{
+       if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
+               pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port."
+                      "\n");
+               return -EIO;
+       }
+
+       i8042_ctr &= ~I8042_CTR_KBDDIS;
+       i8042_ctr |= I8042_CTR_KBDINT;
+
+       if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+               i8042_ctr &= ~I8042_CTR_KBDINT;
+               i8042_ctr |= I8042_CTR_KBDDIS;
+               pr_err("i8042.c: Failed to enable KBD port.\n");
+
+               return -EIO;
+       }
+
+       return 0;
+}
+
+void setup_wakeup_events(void)
+{
+       int irq_mask;
+
+       switch (mips_machtype) {
+       case MACH_LEMOTE_ML2F7:
+       case MACH_LEMOTE_YL2F89:
+               /* open the keyboard irq in i8259A */
+               outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR);
+               irq_mask = inb(PIC_MASTER_IMR);
+
+               /* enable keyboard port */
+               i8042_enable_kbd_port();
+
+               /* Wakeup CPU via SCI lid open event */
+               outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR);
+               inb(PIC_MASTER_IMR);
+               outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR);
+               inb(PIC_SLAVE_IMR);
+
+               break;
+
+       default:
+               break;
+       }
+}
+
+static struct delayed_work lid_task;
+static int initialized;
+/* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
+sci_handler yeeloong_report_lid_status;
+EXPORT_SYMBOL(yeeloong_report_lid_status);
+static void yeeloong_lid_update_task(struct work_struct *work)
+{
+       if (yeeloong_report_lid_status)
+               yeeloong_report_lid_status(BIT_LID_DETECT_ON);
+}
+
+int wakeup_loongson(void)
+{
+       int irq;
+
+       /* query the interrupt number */
+       irq = mach_i8259_irq();
+       if (irq < 0)
+               return 0;
+
+       printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
+
+       if (irq == I8042_KBD_IRQ)
+               return 1;
+       else if (irq == SCI_IRQ_NUM) {
+               int ret, sci_event;
+               /* query the event number */
+               ret = ec_query_seq(CMD_GET_EVENT_NUM);
+               if (ret < 0)
+                       return 0;
+               sci_event = ec_get_event_num();
+               if (sci_event < 0)
+                       return 0;
+               if (sci_event == EVENT_LID) {
+                       int lid_status;
+                       /* check the LID status */
+                       lid_status = ec_read(REG_LID_DETECT);
+                       /* wakeup cpu when people open the LID */
+                       if (lid_status == BIT_LID_DETECT_ON) {
+                               /* If we call it directly here, the WARNING
+                                * will be sent out by getnstimeofday
+                                * via "WARN_ON(timekeeping_suspended);"
+                                * because we can not schedule in suspend mode.
+                                */
+                               if (initialized == 0) {
+                                       INIT_DELAYED_WORK(&lid_task,
+                                               yeeloong_lid_update_task);
+                                       initialized = 1;
+                               }
+                               schedule_delayed_work(&lid_task, 1);
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+void __weak mach_suspend(void)
+{
+       disable_mfgpt0_counter();
+}
+
+void __weak mach_resume(void)
+{
+       enable_mfgpt0_counter();
+}
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c
new file mode 100644 (file)
index 0000000..51d1a60
--- /dev/null
@@ -0,0 +1,159 @@
+/* Board-specific reboot/shutdown routines
+ *
+ * Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+#include <cs5536/cs5536.h>
+#include "ec_kb3310b.h"
+
+static void reset_cpu(void)
+{
+       /*
+        * reset cpu to full speed, this is needed when enabling cpu frequency
+        * scalling
+        */
+       LOONGSON_CHIPCFG0 |= 0x7;
+}
+
+/* reset support for fuloong2f */
+
+static void fl2f_reboot(void)
+{
+       reset_cpu();
+
+       /* send a reset signal to south bridge.
+        *
+        * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset
+        * normally with this reset operation and it will not work in PMON, but
+        * you can type halt command and then reboot, seems the hardware reset
+        * logic not work normally.
+        */
+       {
+               u32 hi, lo;
+               _rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo);
+               lo |= 0x00000001;
+               _wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo);
+       }
+}
+
+static void fl2f_shutdown(void)
+{
+       u32 hi, lo, val;
+       int gpio_base;
+
+       /* get gpio base */
+       _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo);
+       gpio_base = lo & 0xff00;
+
+       /* make cs5536 gpio13 output enable */
+       val = inl(gpio_base + GPIOL_OUT_EN);
+       val &= ~(1 << (16 + 13));
+       val |= (1 << 13);
+       outl(val, gpio_base + GPIOL_OUT_EN);
+       mmiowb();
+       /* make cs5536 gpio13 output low level voltage. */
+       val = inl(gpio_base + GPIOL_OUT_VAL) & ~(1 << (13));
+       val |= (1 << (16 + 13));
+       outl(val, gpio_base + GPIOL_OUT_VAL);
+       mmiowb();
+}
+
+/* reset support for yeeloong2f and mengloong2f notebook */
+
+void ml2f_reboot(void)
+{
+       reset_cpu();
+
+       /* sending an reset signal to EC(embedded controller) */
+       ec_write(REG_RESET, BIT_RESET_ON);
+}
+
+#define yl2f89_reboot ml2f_reboot
+
+/* menglong(7inches) laptop has different shutdown logic from 8.9inches */
+#define EC_SHUTDOWN_IO_PORT_HIGH 0xff2d
+#define EC_SHUTDOWN_IO_PORT_LOW         0xff2e
+#define EC_SHUTDOWN_IO_PORT_DATA 0xff2f
+#define REG_SHUTDOWN_HIGH        0xFC
+#define REG_SHUTDOWN_LOW         0x29
+#define BIT_SHUTDOWN_ON          (1 << 1)
+
+static void ml2f_shutdown(void)
+{
+       u8 val;
+       u64 i;
+
+       outb(REG_SHUTDOWN_HIGH, EC_SHUTDOWN_IO_PORT_HIGH);
+       outb(REG_SHUTDOWN_LOW, EC_SHUTDOWN_IO_PORT_LOW);
+       mmiowb();
+       val = inb(EC_SHUTDOWN_IO_PORT_DATA);
+       outb(val & (~BIT_SHUTDOWN_ON), EC_SHUTDOWN_IO_PORT_DATA);
+       mmiowb();
+       /* need enough wait here... how many microseconds needs? */
+       for (i = 0; i < 0x10000; i++)
+               delay();
+       outb(val | BIT_SHUTDOWN_ON, EC_SHUTDOWN_IO_PORT_DATA);
+       mmiowb();
+}
+
+static void yl2f89_shutdown(void)
+{
+       /* cpu-gpio0 output low */
+       LOONGSON_GPIODATA &= ~0x00000001;
+       /* cpu-gpio0 as output */
+       LOONGSON_GPIOIE &= ~0x00000001;
+}
+
+void mach_prepare_reboot(void)
+{
+       switch (mips_machtype) {
+       case MACH_LEMOTE_FL2F:
+       case MACH_LEMOTE_NAS:
+       case MACH_LEMOTE_LL2F:
+               fl2f_reboot();
+               break;
+       case MACH_LEMOTE_ML2F7:
+               ml2f_reboot();
+               break;
+       case MACH_LEMOTE_YL2F89:
+               yl2f89_reboot();
+               break;
+       default:
+               break;
+       }
+}
+
+void mach_prepare_shutdown(void)
+{
+       switch (mips_machtype) {
+       case MACH_LEMOTE_FL2F:
+       case MACH_LEMOTE_NAS:
+       case MACH_LEMOTE_LL2F:
+               fl2f_shutdown();
+               break;
+       case MACH_LEMOTE_ML2F7:
+               ml2f_shutdown();
+               break;
+       case MACH_LEMOTE_YL2F89:
+               yl2f89_shutdown();
+               break;
+       default:
+               break;
+       }
+}
index 454b539..8f2f8e9 100644 (file)
@@ -35,6 +35,7 @@
  * better performance by compiling with -msoft-float!
  */
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/debugfs.h>
 
 #include <asm/inst.h>
@@ -68,7 +69,9 @@ static int fpux_emu(struct pt_regs *,
 
 /* Further private data for which no space exists in mips_fpu_struct */
 
-struct mips_fpu_emulator_stats fpuemustats;
+#ifdef CONFIG_DEBUG_FS
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+#endif
 
 /* Control registers */
 
@@ -209,7 +212,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
        unsigned int cond;
 
        if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
-               fpuemustats.errors++;
+               MIPS_FPU_EMU_INC_STATS(errors);
                return SIGBUS;
        }
 
@@ -240,7 +243,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                        return SIGILL;
                }
                if (get_user(ir, (mips_instruction __user *) emulpc)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                /* __compute_return_epc() will have updated cp0_epc */
@@ -253,16 +256,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
        }
 
       emul:
-       fpuemustats.emulated++;
+       MIPS_FPU_EMU_INC_STATS(emulated);
        switch (MIPSInst_OPCODE(ir)) {
        case ldc1_op:{
                u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
                        MIPSInst_SIMM(ir));
                u64 val;
 
-               fpuemustats.loads++;
+               MIPS_FPU_EMU_INC_STATS(loads);
                if (get_user(val, va)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                DITOREG(val, MIPSInst_RT(ir));
@@ -274,10 +277,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                        MIPSInst_SIMM(ir));
                u64 val;
 
-               fpuemustats.stores++;
+               MIPS_FPU_EMU_INC_STATS(stores);
                DIFROMREG(val, MIPSInst_RT(ir));
                if (put_user(val, va)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                break;
@@ -288,9 +291,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                        MIPSInst_SIMM(ir));
                u32 val;
 
-               fpuemustats.loads++;
+               MIPS_FPU_EMU_INC_STATS(loads);
                if (get_user(val, va)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                SITOREG(val, MIPSInst_RT(ir));
@@ -302,10 +305,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                        MIPSInst_SIMM(ir));
                u32 val;
 
-               fpuemustats.stores++;
+               MIPS_FPU_EMU_INC_STATS(stores);
                SIFROMREG(val, MIPSInst_RT(ir));
                if (put_user(val, va)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                break;
@@ -429,7 +432,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                                if (get_user(ir,
                                    (mips_instruction __user *) xcp->cp0_epc)) {
-                                       fpuemustats.errors++;
+                                       MIPS_FPU_EMU_INC_STATS(errors);
                                        return SIGBUS;
                                }
 
@@ -595,7 +598,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 {
        unsigned rcsr = 0;      /* resulting csr */
 
-       fpuemustats.cp1xops++;
+       MIPS_FPU_EMU_INC_STATS(cp1xops);
 
        switch (MIPSInst_FMA_FFMT(ir)) {
        case s_fmt:{            /* 0 */
@@ -610,9 +613,9 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemustats.loads++;
+                       MIPS_FPU_EMU_INC_STATS(loads);
                        if (get_user(val, va)) {
-                               fpuemustats.errors++;
+                               MIPS_FPU_EMU_INC_STATS(errors);
                                return SIGBUS;
                        }
                        SITOREG(val, MIPSInst_FD(ir));
@@ -622,11 +625,11 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemustats.stores++;
+                       MIPS_FPU_EMU_INC_STATS(stores);
 
                        SIFROMREG(val, MIPSInst_FS(ir));
                        if (put_user(val, va)) {
-                               fpuemustats.errors++;
+                               MIPS_FPU_EMU_INC_STATS(errors);
                                return SIGBUS;
                        }
                        break;
@@ -687,9 +690,9 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemustats.loads++;
+                       MIPS_FPU_EMU_INC_STATS(loads);
                        if (get_user(val, va)) {
-                               fpuemustats.errors++;
+                               MIPS_FPU_EMU_INC_STATS(errors);
                                return SIGBUS;
                        }
                        DITOREG(val, MIPSInst_FD(ir));
@@ -699,10 +702,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
                                xcp->regs[MIPSInst_FT(ir)]);
 
-                       fpuemustats.stores++;
+                       MIPS_FPU_EMU_INC_STATS(stores);
                        DIFROMREG(val, MIPSInst_FS(ir));
                        if (put_user(val, va)) {
-                               fpuemustats.errors++;
+                               MIPS_FPU_EMU_INC_STATS(errors);
                                return SIGBUS;
                        }
                        break;
@@ -769,7 +772,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 #endif
        } rv;                   /* resulting value */
 
-       fpuemustats.cp1ops++;
+       MIPS_FPU_EMU_INC_STATS(cp1ops);
        switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
        case s_fmt:{            /* 0 */
                union {
@@ -1240,7 +1243,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                prevepc = xcp->cp0_epc;
 
                if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
-                       fpuemustats.errors++;
+                       MIPS_FPU_EMU_INC_STATS(errors);
                        return SIGBUS;
                }
                if (insn == 0)
@@ -1276,33 +1279,50 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 }
 
 #ifdef CONFIG_DEBUG_FS
+
+static int fpuemu_stat_get(void *data, u64 *val)
+{
+       int cpu;
+       unsigned long sum = 0;
+       for_each_online_cpu(cpu) {
+               struct mips_fpu_emulator_stats *ps;
+               local_t *pv;
+               ps = &per_cpu(fpuemustats, cpu);
+               pv = (void *)ps + (unsigned long)data;
+               sum += local_read(pv);
+       }
+       *val = sum;
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
+
 extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_fpuemu(void)
 {
        struct dentry *d, *dir;
-       int i;
-       static struct {
-               const char *name;
-               unsigned int *v;
-       } vars[] __initdata = {
-               { "emulated", &fpuemustats.emulated },
-               { "loads",    &fpuemustats.loads },
-               { "stores",   &fpuemustats.stores },
-               { "cp1ops",   &fpuemustats.cp1ops },
-               { "cp1xops",  &fpuemustats.cp1xops },
-               { "errors",   &fpuemustats.errors },
-       };
 
        if (!mips_debugfs_dir)
                return -ENODEV;
        dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
        if (!dir)
                return -ENOMEM;
-       for (i = 0; i < ARRAY_SIZE(vars); i++) {
-               d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
-               if (!d)
-                       return -ENOMEM;
-       }
+
+#define FPU_STAT_CREATE(M)                                             \
+       do {                                                            \
+               d = debugfs_create_file(#M , S_IRUGO, dir,              \
+                       (void *)offsetof(struct mips_fpu_emulator_stats, M), \
+                       &fops_fpuemu_stat);                             \
+               if (!d)                                                 \
+                       return -ENOMEM;                                 \
+       } while (0)
+
+       FPU_STAT_CREATE(emulated);
+       FPU_STAT_CREATE(loads);
+       FPU_STAT_CREATE(stores);
+       FPU_STAT_CREATE(cp1ops);
+       FPU_STAT_CREATE(cp1xops);
+       FPU_STAT_CREATE(errors);
+
        return 0;
 }
 __initcall(debugfs_fpuemu);
index df7b9d9..36d975a 100644 (file)
@@ -98,7 +98,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
        err |= __put_user(cpc, &fr->epc);
 
        if (unlikely(err)) {
-               fpuemustats.errors++;
+               MIPS_FPU_EMU_INC_STATS(errors);
                return SIGBUS;
        }
 
@@ -136,7 +136,7 @@ int do_dsemulret(struct pt_regs *xcp)
        err |= __get_user(cookie, &fr->cookie);
 
        if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
-               fpuemustats.errors++;
+               MIPS_FPU_EMU_INC_STATS(errors);
                return 0;
        }
 
index 57f43c1..41b9657 100644 (file)
@@ -17,8 +17,7 @@
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
 
-obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \
-        sim_cmdline.o
+obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o
 
 obj-$(CONFIG_EARLY_PRINTK) += sim_console.o
 obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o
index 2877675..0824f6a 100644 (file)
@@ -61,7 +61,6 @@ void __init prom_init(void)
        set_io_port_base(0xbfd00000);
 
        pr_info("\nLINUX started...\n");
-       prom_init_cmdline();
        prom_meminit();
 
 #ifdef CONFIG_MIPS_MT_SMP
index 1bd1f18..3571090 100644 (file)
@@ -567,13 +567,10 @@ static uint32_t extract_dc(unsigned short addr, int data)
                                datalo = ((unsigned long long)datalohi << 32) | datalolo;
                                ecc = dc_ecc(datalo);
                                if (ecc != datahi) {
-                                       int bits = 0;
+                                       int bits;
                                        bad_ecc |= 1 << (3-offset);
                                        ecc ^= datahi;
-                                       while (ecc) {
-                                               if (ecc & 1) bits++;
-                                               ecc >>= 1;
-                                       }
+                                       bits = hweight8(ecc);
                                        res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
                                }
                                printk("  %02X-%016llX", datahi, datalo);
index 8d1f4f3..9e8d003 100644 (file)
@@ -462,7 +462,9 @@ void __init_refok free_initmem(void)
                        __pa_symbol(&__init_end));
 }
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 unsigned long pgd_current[NR_CPUS];
+#endif
 /*
  * On 64-bit we've got three-level pagetables with a slightly
  * different layout ...
index bb1719a..3d0baa4 100644 (file)
@@ -160,6 +160,12 @@ static u32 tlb_handler[128] __cpuinitdata;
 static struct uasm_label labels[128] __cpuinitdata;
 static struct uasm_reloc relocs[128] __cpuinitdata;
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+/*
+ * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
+ * we cannot do r3000 under these circumstances.
+ */
+
 /*
  * The R3000 TLB handler is simple.
  */
@@ -199,6 +205,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
 
        dump_handler((u32 *)ebase, 32);
 }
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
 /*
  * The R4000 TLB handler is much more complicated. We have two
@@ -497,8 +504,9 @@ static void __cpuinit
 build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
                 unsigned int tmp, unsigned int ptr)
 {
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
        long pgdc = (long)pgd_current;
-
+#endif
        /*
         * The vmalloc handling is not in the hotpath.
         */
@@ -506,7 +514,15 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
        uasm_il_bltz(p, r, tmp, label_vmalloc);
        /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+       /*
+        * &pgd << 11 stored in CONTEXT [23..63].
+        */
+       UASM_i_MFC0(p, ptr, C0_CONTEXT);
+       uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */
+       uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0  1 0 1  << 6  xkphys cached */
+       uasm_i_drotr(p, ptr, ptr, 11);
+#elif defined(CONFIG_SMP)
 # ifdef  CONFIG_MIPS_MT_SMTC
        /*
         * SMTC uses TCBind value as "CPU" index
@@ -520,7 +536,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
         */
        uasm_i_dmfc0(p, ptr, C0_CONTEXT);
        uasm_i_dsrl(p, ptr, ptr, 23);
-#endif
+# endif
        UASM_i_LA_mostly(p, tmp, pgdc);
        uasm_i_daddu(p, ptr, ptr, tmp);
        uasm_i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1033,6 +1049,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r,
        iPTE_LW(p, pte, ptr);
 }
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 /*
  * R3000 style TLB load/store/modify handlers.
  */
@@ -1184,6 +1201,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
 
        dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
 /*
  * R4000 style TLB load/store/modify handlers.
@@ -1400,6 +1418,7 @@ void __cpuinit build_tlb_refill_handler(void)
        case CPU_TX3912:
        case CPU_TX3922:
        case CPU_TX3927:
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
                build_r3000_tlb_refill_handler();
                if (!run_once) {
                        build_r3000_tlb_load_handler();
@@ -1407,6 +1426,9 @@ void __cpuinit build_tlb_refill_handler(void)
                        build_r3000_tlb_modify_handler();
                        run_once++;
                }
+#else
+               panic("No R3000 TLB refill handler");
+#endif
                break;
 
        case CPU_R6000:
index f467199..0a165c5 100644 (file)
@@ -60,11 +60,11 @@ enum opcode {
        insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
        insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0,
        insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
-       insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr,
-       insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
+       insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal,
+       insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
        insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
        insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
-       insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori
+       insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins
 };
 
 struct insn {
@@ -104,6 +104,7 @@ static struct insn insn_table[] __cpuinitdata = {
        { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
        { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
        { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
+       { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
        { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
        { insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
        { insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
@@ -132,6 +133,7 @@ static struct insn insn_table[] __cpuinitdata = {
        { insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
        { insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
        { insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
+       { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
        { insn_invalid, 0, 0 }
 };
 
@@ -304,6 +306,12 @@ Ip_u2u1s3(op)                                              \
        build_insn(buf, insn##op, b, a, c);             \
 }
 
+#define I_u2u1msbu3(op)                                        \
+Ip_u2u1msbu3(op)                                       \
+{                                                      \
+       build_insn(buf, insn##op, b, a, c+d-1, c);      \
+}
+
 #define I_u1u2(op)                                     \
 Ip_u1u2(op)                                            \
 {                                                      \
@@ -349,6 +357,7 @@ I_u2u1u3(_dsll32)
 I_u2u1u3(_dsra)
 I_u2u1u3(_dsrl)
 I_u2u1u3(_dsrl32)
+I_u2u1u3(_drotr)
 I_u3u1u2(_dsubu)
 I_0(_eret)
 I_u1(_j)
@@ -377,6 +386,7 @@ I_0(_tlbwi)
 I_0(_tlbwr)
 I_u3u1u2(_xor)
 I_u2u1u3(_xori)
+I_u2u1msbu3(_dins);
 
 /* Handle labels. */
 void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
index c6d1e3d..3d153ed 100644 (file)
@@ -34,6 +34,11 @@ uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c)
 void __cpuinit                                                         \
 uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
+#define Ip_u2u1msbu3(op)                                               \
+void __cpuinit                                                         \
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c,  \
+          unsigned int d)
+
 #define Ip_u1u2(op)                                                    \
 void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
 
@@ -65,6 +70,7 @@ Ip_u2u1u3(_dsll32);
 Ip_u2u1u3(_dsra);
 Ip_u2u1u3(_dsrl);
 Ip_u2u1u3(_dsrl32);
+Ip_u2u1u3(_drotr);
 Ip_u3u1u2(_dsubu);
 Ip_0(_eret);
 Ip_u1(_j);
@@ -93,6 +99,7 @@ Ip_0(_tlbwi);
 Ip_0(_tlbwr);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
+Ip_u2u1msbu3(_dins);
 
 /* Handle labels. */
 struct uasm_label {
index 9035c64..b27419c 100644 (file)
@@ -55,7 +55,7 @@ static struct prom_pmemblock * __init prom_getmdesc(void)
        char *memsize_str;
        unsigned int memsize;
        char *ptr;
-       static char cmdline[CL_SIZE] __initdata;
+       static char cmdline[COMMAND_LINE_SIZE] __initdata;
 
        /* otherwise look in the environment */
        memsize_str = prom_getenv("memsize");
index 30533ba..3a467c0 100644 (file)
@@ -295,7 +295,7 @@ static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type)
 }
 
 static struct irq_chip pnx833x_pic_irq_type = {
-       .typename = "PNX-PIC",
+       .name = "PNX-PIC",
        .startup = pnx833x_startup_pic_irq,
        .shutdown = pnx833x_shutdown_pic_irq,
        .enable = pnx833x_enable_pic_irq,
@@ -305,7 +305,7 @@ static struct irq_chip pnx833x_pic_irq_type = {
 };
 
 static struct irq_chip pnx833x_gpio_irq_type = {
-       .typename = "PNX-GPIO",
+       .name = "PNX-GPIO",
        .startup = pnx833x_startup_gpio_irq,
        .shutdown = pnx833x_disable_gpio_irq,
        .enable = pnx833x_enable_gpio_irq,
index 575cd14..475ff46 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Loongson2 performance counter driver for oprofile
  *
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Yanhua <yanh@lemote.com>
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
@@ -125,6 +125,9 @@ static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id)
         */
 
        /* Check whether the irq belongs to me */
+       enabled = read_c0_perfcnt() & LOONGSON2_PERFCNT_INT_EN;
+       if (!enabled)
+               return IRQ_NONE;
        enabled = reg.cnt1_enabled | reg.cnt2_enabled;
        if (!enabled)
                return IRQ_NONE;
index 91bfe73..c9209ca 100644 (file)
@@ -22,13 +22,13 @@ obj-$(CONFIG_BCM63XX)               += pci-bcm63xx.o fixup-bcm63xx.o \
 #
 # These are still pretty much in the old state, watch, go blind.
 #
-obj-$(CONFIG_BASLER_EXCITE)    += ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_LASAT)            += pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)      += fixup-cobalt.o
 obj-$(CONFIG_SOC_AU1500)       += fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_AU1550)       += fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)      += fixup-pnx8550.o ops-pnx8550.o
-obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-bonito64.o
+obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
+obj-$(CONFIG_LEMOTE_MACH2F)    += fixup-lemote2f.o ops-loongson2.o
 obj-$(CONFIG_MIPS_MALTA)       += fixup-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)   += fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
deleted file mode 100644 (file)
index cd64d9f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <excite.h>
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-       if (pin == 0)
-               return -1;
-
-       return USB_IRQ;         /* USB controller is the only PCI device */
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
index 0c4c7a8..4f6d8da 100644 (file)
@@ -13,7 +13,8 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <asm/mips-boards/bonito64.h>
+
+#include <loongson.h>
 
 /* South bridge slot number is set by the pci probe process */
 static u8 sb_slot = 5;
@@ -35,7 +36,7 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
                        break;
                }
        } else {
-               irq = BONITO_IRQ_BASE + 25 + pin;
+               irq = LOONGSON_IRQ_BASE + 25 + pin;
        }
        return irq;
 
diff --git a/arch/mips/pci/fixup-lemote2f.c b/arch/mips/pci/fixup-lemote2f.c
new file mode 100644 (file)
index 0000000..caf2ede
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 Lemote Technology
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <loongson.h>
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* PCI interrupt pins
+ *
+ * These should not be changed, or you should consider loongson2f interrupt
+ * register and your pci card dispatch
+ */
+
+#define PCIA           4
+#define PCIB           5
+#define PCIC           6
+#define PCID           7
+
+/* all the pci device has the PCIA pin, check the datasheet. */
+static char irq_tab[][5] __initdata = {
+       /*      INTA    INTB    INTC    INTD */
+       {0, 0, 0, 0, 0},        /*  11: Unused */
+       {0, 0, 0, 0, 0},        /*  12: Unused */
+       {0, 0, 0, 0, 0},        /*  13: Unused */
+       {0, 0, 0, 0, 0},        /*  14: Unused */
+       {0, 0, 0, 0, 0},        /*  15: Unused */
+       {0, 0, 0, 0, 0},        /*  16: Unused */
+       {0, PCIA, 0, 0, 0},     /*  17: RTL8110-0 */
+       {0, PCIB, 0, 0, 0},     /*  18: RTL8110-1 */
+       {0, PCIC, 0, 0, 0},     /*  19: SiI3114 */
+       {0, PCID, 0, 0, 0},     /*  20: 3-ports nec usb */
+       {0, PCIA, PCIB, PCIC, PCID},    /*  21: PCI-SLOT */
+       {0, 0, 0, 0, 0},        /*  22: Unused */
+       {0, 0, 0, 0, 0},        /*  23: Unused */
+       {0, 0, 0, 0, 0},        /*  24: Unused */
+       {0, 0, 0, 0, 0},        /*  25: Unused */
+       {0, 0, 0, 0, 0},        /*  26: Unused */
+       {0, 0, 0, 0, 0},        /*  27: Unused */
+};
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int virq;
+
+       if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536)
+           && (PCI_SLOT(dev->devfn) < 32)) {
+               virq = irq_tab[slot][pin];
+               printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin,
+                      virq + LOONGSON_IRQ_BASE);
+               if (virq != 0)
+                       return LOONGSON_IRQ_BASE + virq;
+               else
+                       return 0;
+       } else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) {  /*  cs5536 */
+               switch (PCI_FUNC(dev->devfn)) {
+               case 2:
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+                                             CS5536_IDE_INTR);
+                       return CS5536_IDE_INTR; /*  for IDE */
+               case 3:
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+                                             CS5536_ACC_INTR);
+                       return CS5536_ACC_INTR; /*  for AUDIO */
+               case 4: /*  for OHCI */
+               case 5: /*  for EHCI */
+               case 6: /*  for UDC */
+               case 7: /*  for OTG */
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+                                             CS5536_USB_INTR);
+                       return CS5536_USB_INTR;
+               }
+               return dev->irq;
+       } else {
+               printk(KERN_INFO " strange pci slot number.\n");
+               return 0;
+       }
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
+
+/* CS5536 SPEC. fixup */
+static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+{
+       /* the uart1 and uart2 interrupt in PIC is enabled as default */
+       pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
+       pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
+}
+
+static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+{
+       /* setting the mutex pin as IDE function */
+       pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
+                              CS5536_IDE_FLASH_SIGNATURE);
+}
+
+static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+{
+       /* enable the AUDIO interrupt in PIC  */
+       pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
+
+       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
+}
+
+static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+{
+       /* enable the OHCI interrupt in PIC */
+       /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
+       pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
+}
+
+static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+{
+       u32 hi, lo;
+
+       /* Serial short detect enable */
+       _rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo);
+       _wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 2) | (1 << 3), lo);
+
+       /* setting the USB2.0 micro frame length */
+       pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
+}
+
+static void __init loongson_nec_fixup(struct pci_dev *pdev)
+{
+       unsigned int val;
+
+       pci_read_config_dword(pdev, 0xe0, &val);
+       /* Only 2 port be used */
+       pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+                        loongson_cs5536_isa_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC,
+                        loongson_cs5536_ohci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC,
+                        loongson_cs5536_ehci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
+                        loongson_cs5536_acc_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE,
+                        loongson_cs5536_ide_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+                        loongson_nec_fixup);
index 54e55e7..1b3e03f 100644 (file)
 #define PCI_ACCESS_READ  0
 #define PCI_ACCESS_WRITE 1
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
-#define ID_SEL_BEGIN 11
-#else
 #define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
 #define ID_SEL_BEGIN 10
-#endif
 #define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
 
 
@@ -77,10 +72,8 @@ static int bonito64_pcibios_config_access(unsigned char access_type,
        addrp = CFG_SPACE_REG(addr & 0xffff);
        if (access_type == PCI_ACCESS_WRITE) {
                writel(cpu_to_le32(*data), addrp);
-#ifndef CONFIG_LEMOTE_FULOONG2E
                /* Wait till done */
                while (BONITO_PCIMSTAT & 0xF);
-#endif
        } else {
                *data = le32_to_cpu(readl(addrp));
        }
diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c
new file mode 100644 (file)
index 0000000..aa5d3da
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * fuloong2e specific PCI support.
+ *
+ * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
+ *     All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <loongson.h>
+
+#ifdef CONFIG_CS5536
+#include <cs5536/cs5536_pci.h>
+#include <cs5536/cs5536.h>
+#endif
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#define CFG_SPACE_REG(offset) \
+       (void *)CKSEG1ADDR(LOONGSON_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
+
+
+static int loongson_pcibios_config_access(unsigned char access_type,
+                                     struct pci_bus *bus,
+                                     unsigned int devfn, int where,
+                                     u32 *data)
+{
+       u32 busnum = bus->number;
+       u32 addr, type;
+       u32 dummy;
+       void *addrp;
+       int device = PCI_SLOT(devfn);
+       int function = PCI_FUNC(devfn);
+       int reg = where & ~3;
+
+       if (busnum == 0) {
+               /* board-specific part,currently,only fuloong2f,yeeloong2f
+                * use CS5536, fuloong2e use via686b, gdium has no
+                * south bridge
+                */
+#ifdef CONFIG_CS5536
+               /* cs5536_pci_conf_read4/write4() will call _rdmsr/_wrmsr() to
+                * access the regsters PCI_MSR_ADDR, PCI_MSR_DATA_LO,
+                * PCI_MSR_DATA_HI, which is bigger than PCI_MSR_CTRL, so, it
+                * will not go this branch, but the others. so, no calling dead
+                * loop here.
+                */
+               if ((PCI_IDSEL_CS5536 == device) && (reg < PCI_MSR_CTRL)) {
+                       switch (access_type) {
+                       case PCI_ACCESS_READ:
+                               *data = cs5536_pci_conf_read4(function, reg);
+                               break;
+                       case PCI_ACCESS_WRITE:
+                               cs5536_pci_conf_write4(function, reg, *data);
+                               break;
+                       }
+                       return 0;
+               }
+#endif
+               /* Type 0 configuration for onboard PCI bus */
+               if (device > MAX_DEV_NUM)
+                       return -1;
+
+               addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+               type = 0;
+       } else {
+               /* Type 1 configuration for offboard PCI bus */
+               addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+               type = 0x10000;
+       }
+
+       /* Clear aborts */
+       LOONGSON_PCICMD |= LOONGSON_PCICMD_MABORT_CLR | \
+                               LOONGSON_PCICMD_MTABORT_CLR;
+
+       LOONGSON_PCIMAP_CFG = (addr >> 16) | type;
+
+       /* Flush Bonito register block */
+       dummy = LOONGSON_PCIMAP_CFG;
+       mmiowb();
+
+       addrp = CFG_SPACE_REG(addr & 0xffff);
+       if (access_type == PCI_ACCESS_WRITE)
+               writel(cpu_to_le32(*data), addrp);
+       else
+               *data = le32_to_cpu(readl(addrp));
+
+       /* Detect Master/Target abort */
+       if (LOONGSON_PCICMD & (LOONGSON_PCICMD_MABORT_CLR |
+                            LOONGSON_PCICMD_MTABORT_CLR)) {
+               /* Error occurred */
+
+               /* Clear bits */
+               LOONGSON_PCICMD |= (LOONGSON_PCICMD_MABORT_CLR |
+                                 LOONGSON_PCICMD_MTABORT_CLR);
+
+               return -1;
+       }
+
+       return 0;
+
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int loongson_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+                            int where, int size, u32 *val)
+{
+       u32 data = 0;
+
+       if ((size == 2) && (where & 1))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       else if ((size == 4) && (where & 3))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+                                      &data))
+               return -1;
+
+       if (size == 1)
+               *val = (data >> ((where & 3) << 3)) & 0xff;
+       else if (size == 2)
+               *val = (data >> ((where & 3) << 3)) & 0xffff;
+       else
+               *val = data;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+                             int where, int size, u32 val)
+{
+       u32 data = 0;
+
+       if ((size == 2) && (where & 1))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       else if ((size == 4) && (where & 3))
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (size == 4)
+               data = val;
+       else {
+               if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+                                       where, &data))
+                       return -1;
+
+               if (size == 1)
+                       data = (data & ~(0xff << ((where & 3) << 3))) |
+                               (val << ((where & 3) << 3));
+               else if (size == 2)
+                       data = (data & ~(0xffff << ((where & 3) << 3))) |
+                               (val << ((where & 3) << 3));
+       }
+
+       if (loongson_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+                                      &data))
+               return -1;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops loongson_pci_ops = {
+       .read = loongson_pcibios_read,
+       .write = loongson_pcibios_write
+};
+
+#ifdef CONFIG_CS5536
+void _rdmsr(u32 msr, u32 *hi, u32 *lo)
+{
+       struct pci_bus bus = {
+               .number = PCI_BUS_CS5536
+       };
+       u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+       loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+       loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+       loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_rdmsr);
+
+void _wrmsr(u32 msr, u32 hi, u32 lo)
+{
+       struct pci_bus bus = {
+               .number = PCI_BUS_CS5536
+       };
+       u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+       loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+       loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+       loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_wrmsr);
+#endif
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
deleted file mode 100644 (file)
index 8a56876..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/rm9k-ocd.h>
-#include <excite.h>
-
-
-extern struct pci_ops titan_pci_ops;
-
-
-static struct resource
-       mem_resource =  {
-               .name   = "PCI memory",
-               .start  = EXCITE_PHYS_PCI_MEM,
-               .end    = EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1,
-               .flags  = IORESOURCE_MEM
-       },
-       io_resource = {
-               .name   = "PCI I/O",
-               .start  = EXCITE_PHYS_PCI_IO,
-               .end    = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1,
-               .flags  = IORESOURCE_IO
-       };
-
-
-static struct pci_controller bx_controller = {
-       .pci_ops        = &titan_pci_ops,
-       .mem_resource   = &mem_resource,
-       .mem_offset     = 0x00000000UL,
-       .io_resource    = &io_resource,
-       .io_offset      = 0x00000000UL
-};
-
-
-static char
-       iopage_failed[] __initdata   = "Cannot allocate PCI I/O page",
-       modebits_no_pci[] __initdata = "PCI is not configured in mode bits";
-
-#define RM9000x2_OCD_HTSC      0x0604
-#define RM9000x2_OCD_HTBHL     0x060c
-#define RM9000x2_OCD_PCIHRST   0x078c
-
-#define RM9K_OCD_MODEBIT1      0x00d4 /* (MODEBIT1) Mode Bit 1 */
-#define RM9K_OCD_CPHDCR                0x00f4 /* CPU-PCI/HT Data Control. */
-
-#define PCISC_FB2B             0x00000200
-#define PCISC_MWICG            0x00000010
-#define PCISC_EMC              0x00000004
-#define PCISC_ERMA             0x00000002
-
-
-
-static int __init basler_excite_pci_setup(void)
-{
-       const unsigned int fullbars = memsize / (256 << 20);
-       unsigned int i;
-
-       /* Check modebits to see if PCI is really enabled. */
-       if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1))
-               panic(modebits_no_pci);
-
-       if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO,
-                                      "Memory-mapped PCI I/O page"))
-               panic(iopage_failed);
-
-       /* Enable PCI 0 as master for config cycles */
-       ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC);
-
-
-       /* Set up latency timer */
-       ocd_writel(0x8008, RM9000x2_OCD_HTBHL);
-
-       /*  Setup host IO and Memory space */
-       ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7);
-       ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7);
-       ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8);
-       ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8);
-
-       /* Set up PCI BARs to map all installed memory */
-       for (i = 0; i < 6; i++) {
-               const unsigned int bar = 0x610 + i * 4;
-
-               if (i < fullbars) {
-                       ocd_writel(0x10000000 * i, bar);
-                       ocd_writel(0x01000000 * i, bar + 0x140);
-                       ocd_writel(0x0ffff029, bar + 0x100);
-                       continue;
-               }
-
-               if (i == fullbars) {
-                       int o;
-                       u32 mask;
-
-                       const unsigned long rem = memsize - i * 0x10000000;
-                       if (!rem) {
-                               ocd_writel(0x00000000, bar + 0x100);
-                               continue;
-                       }
-
-                       o = ffs(rem) - 1;
-                       if (rem & ~(0x1 << o))
-                               o++;
-                       mask = ((0x1 << o) & 0x0ffff000) - 0x1000;
-                       ocd_writel(0x10000000 * i, bar);
-                       ocd_writel(0x01000000 * i, bar + 0x140);
-                       ocd_writel(0x00000029 | mask, bar + 0x100);
-                       continue;
-               }
-
-               ocd_writel(0x00000000, bar + 0x100);
-       }
-
-       /* Finally, enable the PCI interrupt */
-#if USB_IRQ > 7
-       set_c0_intcontrol(1 << USB_IRQ);
-#else
-       set_c0_status(1 << (USB_IRQ + 8));
-#endif
-
-       ioport_resource.start = EXCITE_PHYS_PCI_IO;
-       ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1;
-       set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO));
-       register_pci_controller(&bx_controller);
-       return 0;
-}
-
-
-arch_initcall(basler_excite_pci_setup);
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
new file mode 100644 (file)
index 0000000..ff0e7e3
--- /dev/null
@@ -0,0 +1,21 @@
+source "arch/mips/powertv/asic/Kconfig"
+
+config BOOTLOADER_DRIVER
+       bool "PowerTV Bootloader Driver Support"
+       default n
+       depends on POWERTV
+       help
+         Use this option if you want to load bootloader driver.
+
+config BOOTLOADER_FAMILY
+       string "POWERTV Bootloader Family string"
+       default "85"
+       depends on POWERTV && !BOOTLOADER_DRIVER
+       help
+         This value should be specified when the bootloader driver is disabled
+         and must be exactly two characters long. Families supported are:
+           R1 - RNG-100  R2 - RNG-200
+           A1 - Class A  B1 - Class B
+           E1 - Class E  F1 - Class F
+           44 - 45xx     46 - 46xx
+           85 - 85xx     86 - 86xx
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
new file mode 100644 (file)
index 0000000..2c51671
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+# Portions copyright (C)  2009 Cisco Systems, Inc.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the Cisco PowerTV-specific kernel interface routines
+# under Linux.
+#
+
+obj-y += cmdline.o init.o memory.o reset.o time.o powertv_setup.o asic/ pci/
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/asic/Kconfig b/arch/mips/powertv/asic/Kconfig
new file mode 100644 (file)
index 0000000..2016bfe
--- /dev/null
@@ -0,0 +1,28 @@
+config MIN_RUNTIME_RESOURCES
+       bool "Support for minimum runtime resources"
+       default n
+       depends on POWERTV
+       help
+         Enables support for minimizing the number of (SA asic) runtime
+         resources that are preallocated by the kernel.
+
+config MIN_RUNTIME_DOCSIS
+       bool "Support for minimum DOCSIS resource"
+       default y
+       depends on MIN_RUNTIME_RESOURCES
+       help
+         Enables support for the preallocated DOCSIS resource.
+
+config MIN_RUNTIME_PMEM
+       bool "Support for minimum PMEM resource"
+       default y
+       depends on MIN_RUNTIME_RESOURCES
+       help
+         Enables support for the preallocated Memory resource.
+
+config MIN_RUNTIME_TFTP
+       bool "Support for minimum TFTP resource"
+       default y
+       depends on MIN_RUNTIME_RESOURCES
+       help
+         Enables support for the preallocated TFTP resource.
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
new file mode 100644 (file)
index 0000000..bebfdcf
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2009  Scientific-Atlanta, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This 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
+#
+
+obj-y += asic-calliope.o asic-cronus.o asic-zeus.o asic_devices.o asic_int.o \
+        irq_asic.o prealloc-calliope.o prealloc-cronus.o \
+        prealloc-cronuslite.o prealloc-zeus.o
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c
new file mode 100644 (file)
index 0000000..03d3884
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Calliope ASIC.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map calliope_register_map = {
+       .eic_slow0_strt_add = 0x800000,
+       .eic_cfg_bits = 0x800038,
+       .eic_ready_status = 0x80004c,
+
+       .chipver3 = 0xA00800,
+       .chipver2 = 0xA00804,
+       .chipver1 = 0xA00808,
+       .chipver0 = 0xA0080c,
+
+       /* The registers of IRBlaster */
+       .uart1_intstat = 0xA01800,
+       .uart1_inten = 0xA01804,
+       .uart1_config1 = 0xA01808,
+       .uart1_config2 = 0xA0180C,
+       .uart1_divisorhi = 0xA01810,
+       .uart1_divisorlo = 0xA01814,
+       .uart1_data = 0xA01818,
+       .uart1_status = 0xA0181C,
+
+       .int_stat_3 = 0xA02800,
+       .int_stat_2 = 0xA02804,
+       .int_stat_1 = 0xA02808,
+       .int_stat_0 = 0xA0280c,
+       .int_config = 0xA02810,
+       .int_int_scan = 0xA02818,
+       .ien_int_3 = 0xA02830,
+       .ien_int_2 = 0xA02834,
+       .ien_int_1 = 0xA02838,
+       .ien_int_0 = 0xA0283c,
+       .int_level_3_3 = 0xA02880,
+       .int_level_3_2 = 0xA02884,
+       .int_level_3_1 = 0xA02888,
+       .int_level_3_0 = 0xA0288c,
+       .int_level_2_3 = 0xA02890,
+       .int_level_2_2 = 0xA02894,
+       .int_level_2_1 = 0xA02898,
+       .int_level_2_0 = 0xA0289c,
+       .int_level_1_3 = 0xA028a0,
+       .int_level_1_2 = 0xA028a4,
+       .int_level_1_1 = 0xA028a8,
+       .int_level_1_0 = 0xA028ac,
+       .int_level_0_3 = 0xA028b0,
+       .int_level_0_2 = 0xA028b4,
+       .int_level_0_1 = 0xA028b8,
+       .int_level_0_0 = 0xA028bc,
+       .int_docsis_en = 0xA028F4,
+
+       .mips_pll_setup = 0x980000,
+       .usb_fs = 0x980030,             /* -default 72800028- */
+       .test_bus = 0x9800CC,
+       .crt_spare = 0x9800d4,
+       .usb2_ohci_int_mask = 0x9A000c,
+       .usb2_strap = 0x9A0014,
+       .ehci_hcapbase = 0x9BFE00,
+       .ohci_hc_revision = 0x9BFC00,
+       .bcm1_bs_lmi_steer = 0x9E0004,
+       .usb2_control = 0x9E0054,
+       .usb2_stbus_obc = 0x9BFF00,
+       .usb2_stbus_mess_size = 0x9BFF04,
+       .usb2_stbus_chunk_size = 0x9BFF08,
+
+       .pcie_regs = 0x000000,          /* -doesn't exist- */
+       .tim_ch = 0xA02C10,
+       .tim_cl = 0xA02C14,
+       .gpio_dout = 0xA02c20,
+       .gpio_din = 0xA02c24,
+       .gpio_dir = 0xA02c2C,
+       .watchdog = 0xA02c30,
+       .front_panel = 0x000000,        /* -not used- */
+};
diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c
new file mode 100644 (file)
index 0000000..5f4589c
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Cronus ASIC
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map cronus_register_map = {
+       .eic_slow0_strt_add = 0x000000,
+       .eic_cfg_bits = 0x000038,
+       .eic_ready_status = 0x00004C,
+
+       .chipver3 = 0x2A0800,
+       .chipver2 = 0x2A0804,
+       .chipver1 = 0x2A0808,
+       .chipver0 = 0x2A080C,
+
+       /* The registers of IRBlaster */
+       .uart1_intstat = 0x2A1800,
+       .uart1_inten = 0x2A1804,
+       .uart1_config1 = 0x2A1808,
+       .uart1_config2 = 0x2A180C,
+       .uart1_divisorhi = 0x2A1810,
+       .uart1_divisorlo = 0x2A1814,
+       .uart1_data = 0x2A1818,
+       .uart1_status = 0x2A181C,
+
+       .int_stat_3 = 0x2A2800,
+       .int_stat_2 = 0x2A2804,
+       .int_stat_1 = 0x2A2808,
+       .int_stat_0 = 0x2A280C,
+       .int_config = 0x2A2810,
+       .int_int_scan = 0x2A2818,
+       .ien_int_3 = 0x2A2830,
+       .ien_int_2 = 0x2A2834,
+       .ien_int_1 = 0x2A2838,
+       .ien_int_0 = 0x2A283C,
+       .int_level_3_3 = 0x2A2880,
+       .int_level_3_2 = 0x2A2884,
+       .int_level_3_1 = 0x2A2888,
+       .int_level_3_0 = 0x2A288C,
+       .int_level_2_3 = 0x2A2890,
+       .int_level_2_2 = 0x2A2894,
+       .int_level_2_1 = 0x2A2898,
+       .int_level_2_0 = 0x2A289C,
+       .int_level_1_3 = 0x2A28A0,
+       .int_level_1_2 = 0x2A28A4,
+       .int_level_1_1 = 0x2A28A8,
+       .int_level_1_0 = 0x2A28AC,
+       .int_level_0_3 = 0x2A28B0,
+       .int_level_0_2 = 0x2A28B4,
+       .int_level_0_1 = 0x2A28B8,
+       .int_level_0_0 = 0x2A28BC,
+       .int_docsis_en = 0x2A28F4,
+
+       .mips_pll_setup = 0x1C0000,
+       .usb_fs = 0x1C0018,
+       .test_bus = 0x1C00CC,
+       .crt_spare = 0x1c00d4,
+       .usb2_ohci_int_mask = 0x20000C,
+       .usb2_strap = 0x200014,
+       .ehci_hcapbase = 0x21FE00,
+       .ohci_hc_revision = 0x1E0000,
+       .bcm1_bs_lmi_steer = 0x2E0008,
+       .usb2_control = 0x2E004C,
+       .usb2_stbus_obc = 0x21FF00,
+       .usb2_stbus_mess_size = 0x21FF04,
+       .usb2_stbus_chunk_size = 0x21FF08,
+
+       .pcie_regs = 0x220000,
+       .tim_ch = 0x2A2C10,
+       .tim_cl = 0x2A2C14,
+       .gpio_dout = 0x2A2C20,
+       .gpio_din = 0x2A2C24,
+       .gpio_dir = 0x2A2C2C,
+       .watchdog = 0x2A2C30,
+       .front_panel = 0x2A3800,
+};
diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c
new file mode 100644 (file)
index 0000000..1469daa
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Zeus ASIC
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map zeus_register_map = {
+       .eic_slow0_strt_add = 0x000000,
+       .eic_cfg_bits = 0x000038,
+       .eic_ready_status = 0x00004c,
+
+       .chipver3 = 0x280800,
+       .chipver2 = 0x280804,
+       .chipver1 = 0x280808,
+       .chipver0 = 0x28080c,
+
+       /* The registers of IRBlaster */
+       .uart1_intstat = 0x281800,
+       .uart1_inten = 0x281804,
+       .uart1_config1 = 0x281808,
+       .uart1_config2 = 0x28180C,
+       .uart1_divisorhi = 0x281810,
+       .uart1_divisorlo = 0x281814,
+       .uart1_data = 0x281818,
+       .uart1_status = 0x28181C,
+
+       .int_stat_3 = 0x282800,
+       .int_stat_2 = 0x282804,
+       .int_stat_1 = 0x282808,
+       .int_stat_0 = 0x28280c,
+       .int_config = 0x282810,
+       .int_int_scan = 0x282818,
+       .ien_int_3 = 0x282830,
+       .ien_int_2 = 0x282834,
+       .ien_int_1 = 0x282838,
+       .ien_int_0 = 0x28283c,
+       .int_level_3_3 = 0x282880,
+       .int_level_3_2 = 0x282884,
+       .int_level_3_1 = 0x282888,
+       .int_level_3_0 = 0x28288c,
+       .int_level_2_3 = 0x282890,
+       .int_level_2_2 = 0x282894,
+       .int_level_2_1 = 0x282898,
+       .int_level_2_0 = 0x28289c,
+       .int_level_1_3 = 0x2828a0,
+       .int_level_1_2 = 0x2828a4,
+       .int_level_1_1 = 0x2828a8,
+       .int_level_1_0 = 0x2828ac,
+       .int_level_0_3 = 0x2828b0,
+       .int_level_0_2 = 0x2828b4,
+       .int_level_0_1 = 0x2828b8,
+       .int_level_0_0 = 0x2828bc,
+       .int_docsis_en = 0x2828F4,
+
+       .mips_pll_setup = 0x1a0000,
+       .usb_fs = 0x1a0018,
+       .test_bus = 0x1a0238,
+       .crt_spare = 0x1a0090,
+       .usb2_ohci_int_mask = 0x1e000c,
+       .usb2_strap = 0x1e0014,
+       .ehci_hcapbase = 0x1FFE00,
+       .ohci_hc_revision = 0x1FFC00,
+       .bcm1_bs_lmi_steer = 0x2C0008,
+       .usb2_control = 0x2c01a0,
+       .usb2_stbus_obc = 0x1FFF00,
+       .usb2_stbus_mess_size = 0x1FFF04,
+       .usb2_stbus_chunk_size = 0x1FFF08,
+
+       .pcie_regs = 0x200000,
+       .tim_ch = 0x282C10,
+       .tim_cl = 0x282C14,
+       .gpio_dout = 0x282c20,
+       .gpio_din = 0x282c24,
+       .gpio_dir = 0x282c2C,
+       .watchdog = 0x282c30,
+       .front_panel = 0x283800,
+};
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
new file mode 100644 (file)
index 0000000..bae8288
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ *                   ASIC Device List Intialization
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ *
+ * NOTE: The bootloader allocates persistent memory at an address which is
+ * 16 MiB below the end of the highest address in KSEG0. All fixed
+ * address memory reservations must avoid this region.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <asm/page.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-powertv/asic.h>
+#include <asm/mach-powertv/asic_regs.h>
+#include <asm/mach-powertv/interrupts.h>
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+#include <asm/mach-powertv/kbldr.h>
+#endif
+#include <asm/bootinfo.h>
+
+#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
+
+/*
+ * Forward Prototypes
+ */
+static void pmem_setup_resource(void);
+
+/*
+ * Global Variables
+ */
+enum asic_type asic;
+
+unsigned int platform_features;
+unsigned int platform_family;
+const struct register_map  *register_map;
+EXPORT_SYMBOL(register_map);                   /* Exported for testing */
+unsigned long asic_phy_base;
+unsigned long asic_base;
+EXPORT_SYMBOL(asic_base);                      /* Exported for testing */
+struct resource *gp_resources;
+static bool usb_configured;
+
+/*
+ * Don't recommend to use it directly, it is usually used by kernel internally.
+ * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
+ */
+unsigned long phys_to_bus_offset;
+EXPORT_SYMBOL(phys_to_bus_offset);
+
+/*
+ *
+ * IO Resource Definition
+ *
+ */
+
+struct resource asic_resource = {
+       .name  = "ASIC Resource",
+       .start = 0,
+       .end   = ASIC_IO_SIZE,
+       .flags = IORESOURCE_MEM,
+};
+
+/*
+ *
+ * USB Host Resource Definition
+ *
+ */
+
+static struct resource ehci_resources[] = {
+       {
+               .parent = &asic_resource,
+               .start  = 0,
+               .end    = 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = irq_usbehci,
+               .end    = irq_usbehci,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ehci_device = {
+       .name = "powertv-ehci",
+       .id = 0,
+       .num_resources = 2,
+       .resource = ehci_resources,
+       .dev = {
+               .dma_mask = &ehci_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+};
+
+static struct resource ohci_resources[] = {
+       {
+               .parent = &asic_resource,
+               .start  = 0,
+               .end    = 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = irq_usbohci,
+               .end    = irq_usbohci,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ohci_device = {
+       .name = "powertv-ohci",
+       .id = 0,
+       .num_resources = 2,
+       .resource = ohci_resources,
+       .dev = {
+               .dma_mask = &ohci_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+};
+
+static struct platform_device *platform_devices[] = {
+       &ehci_device,
+       &ohci_device,
+};
+
+/*
+ *
+ * Platform Configuration and Device Initialization
+ *
+ */
+static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3)
+{
+       int en_prg, byp, pwr, nsb, val;
+       int sout;
+
+       sout = 1;
+       en_prg = 1;
+       byp = 0;
+       nsb = 1;
+       pwr = 1;
+
+       val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) |
+               (nsb<<1) | (disable_div_by_3<<5));
+
+       asic_write(val, usb_fs);
+       asic_write(val | (en_prg<<4), usb_fs);
+       asic_write(val | (en_prg<<4) | pwr, usb_fs);
+}
+
+/*
+ * Allow override of bootloader-specified model
+ */
+static char __initdata cmdline[COMMAND_LINE_SIZE];
+
+#define        FORCEFAMILY_PARAM       "forcefamily"
+
+static __init int check_forcefamily(unsigned char forced_family[2])
+{
+       const char *p;
+
+       forced_family[0] = '\0';
+       forced_family[1] = '\0';
+
+       /* Check the command line for a forcefamily directive */
+       strncpy(cmdline, arcs_cmdline, COMMAND_LINE_SIZE - 1);
+       p = strstr(cmdline, FORCEFAMILY_PARAM);
+       if (p && (p != cmdline) && (*(p - 1) != ' '))
+               p = strstr(p, " " FORCEFAMILY_PARAM "=");
+
+       if (p) {
+               p += strlen(FORCEFAMILY_PARAM "=");
+
+               if (*p == '\0' || *(p + 1) == '\0' ||
+                       (*(p + 2) != '\0' && *(p + 2) != ' '))
+                       pr_err(FORCEFAMILY_PARAM " must be exactly two "
+                               "characters long, ignoring value\n");
+
+               else {
+                       forced_family[0] = *p;
+                       forced_family[1] = *(p + 1);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * platform_set_family - determine major platform family type.
+ *
+ * Returns family type; -1 if none
+ * Returns the family type; -1 if none
+ *
+ */
+static __init noinline void platform_set_family(void)
+{
+#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
+
+       unsigned char forced_family[2];
+       unsigned short bootldr_family;
+
+       check_forcefamily(forced_family);
+
+       if (forced_family[0] != '\0' && forced_family[1] != '\0')
+               bootldr_family = BOOTLDRFAMILY(forced_family[0],
+                       forced_family[1]);
+       else {
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+               bootldr_family = (unsigned short) kbldr_GetSWFamily();
+#else
+#if defined(CONFIG_BOOTLOADER_FAMILY)
+               bootldr_family = (unsigned short) BOOTLDRFAMILY(
+                       CONFIG_BOOTLOADER_FAMILY[0],
+                       CONFIG_BOOTLOADER_FAMILY[1]);
+#else
+#error "Unknown Bootloader Family"
+#endif
+#endif
+       }
+
+       pr_info("Bootloader Family = 0x%04X\n", bootldr_family);
+
+       switch (bootldr_family) {
+       case BOOTLDRFAMILY('R', '1'):
+               platform_family = FAMILY_1500;
+               break;
+       case BOOTLDRFAMILY('4', '4'):
+               platform_family = FAMILY_4500;
+               break;
+       case BOOTLDRFAMILY('4', '6'):
+               platform_family = FAMILY_4600;
+               break;
+       case BOOTLDRFAMILY('A', '1'):
+               platform_family = FAMILY_4600VZA;
+               break;
+       case BOOTLDRFAMILY('8', '5'):
+               platform_family = FAMILY_8500;
+               break;
+       case BOOTLDRFAMILY('R', '2'):
+               platform_family = FAMILY_8500RNG;
+               break;
+       case BOOTLDRFAMILY('8', '6'):
+               platform_family = FAMILY_8600;
+               break;
+       case BOOTLDRFAMILY('B', '1'):
+               platform_family = FAMILY_8600VZB;
+               break;
+       case BOOTLDRFAMILY('E', '1'):
+               platform_family = FAMILY_1500VZE;
+               break;
+       case BOOTLDRFAMILY('F', '1'):
+               platform_family = FAMILY_1500VZF;
+               break;
+       default:
+               platform_family = -1;
+       }
+}
+
+unsigned int platform_get_family(void)
+{
+       return platform_family;
+}
+EXPORT_SYMBOL(platform_get_family);
+
+/*
+ * \brief usb_eye_configure() for optimizing the USB eye on Calliope.
+ *
+ * \param     unsigned int value saved to the register.
+ *
+ * \return    none
+ *
+ */
+static void __init usb_eye_configure(unsigned int value)
+{
+       asic_write(asic_read(crt_spare) | value, crt_spare);
+}
+
+/*
+ * platform_get_asic - determine the ASIC type.
+ *
+ * \param     none
+ *
+ * \return    ASIC type; ASIC_UNKNOWN if none
+ *
+ */
+enum asic_type platform_get_asic(void)
+{
+       return asic;
+}
+EXPORT_SYMBOL(platform_get_asic);
+
+/*
+ * platform_configure_usb - usb configuration based on platform type.
+ * @bcm1_usb2_ctl:     value for the BCM1_USB2_CTL register, which is
+ *                     quirky
+ */
+static void __init platform_configure_usb(void)
+{
+       u32 bcm1_usb2_ctl;
+
+       if (usb_configured)
+               return;
+
+       switch (asic) {
+       case ASIC_ZEUS:
+               fs_update(0x0000, 0x11, 0x02, 0);
+               bcm1_usb2_ctl = 0x803;
+               break;
+
+       case ASIC_CRONUS:
+       case ASIC_CRONUSLITE:
+               fs_update(0x0000, 0x11, 0x02, 0);
+               bcm1_usb2_ctl = 0x803;
+               break;
+
+       case ASIC_CALLIOPE:
+               fs_update(0x0000, 0x11, 0x02, 1);
+
+               switch (platform_family) {
+               case FAMILY_1500VZE:
+                       break;
+
+               case FAMILY_1500VZF:
+                       usb_eye_configure(0x003c0000);
+                       break;
+
+               default:
+                       usb_eye_configure(0x00300000);
+                       break;
+               }
+
+               bcm1_usb2_ctl = 0x803;
+               break;
+
+       default:
+               pr_err("Unknown ASIC type: %d\n", asic);
+               break;
+       }
+
+       /* turn on USB power */
+       asic_write(0, usb2_strap);
+       /* Enable all OHCI interrupts */
+       asic_write(bcm1_usb2_ctl, usb2_control);
+       /* USB2_STBUS_OBC store32/load32 */
+       asic_write(3, usb2_stbus_obc);
+       /* USB2_STBUS_MESS_SIZE 2 packets */
+       asic_write(1, usb2_stbus_mess_size);
+       /* USB2_STBUS_CHUNK_SIZE 2 packets */
+       asic_write(1, usb2_stbus_chunk_size);
+
+       usb_configured = true;
+}
+
+/*
+ * Set up the USB EHCI interface
+ */
+void platform_configure_usb_ehci()
+{
+       platform_configure_usb();
+}
+
+/*
+ * Set up the USB OHCI interface
+ */
+void platform_configure_usb_ohci()
+{
+       platform_configure_usb();
+}
+
+/*
+ * Shut the USB EHCI interface down--currently a NOP
+ */
+void platform_unconfigure_usb_ehci()
+{
+}
+
+/*
+ * Shut the USB OHCI interface down--currently a NOP
+ */
+void platform_unconfigure_usb_ohci()
+{
+}
+
+/**
+ * configure_platform - configuration based on platform type.
+ */
+void __init configure_platform(void)
+{
+       platform_set_family();
+
+       switch (platform_family) {
+       case FAMILY_1500:
+       case FAMILY_1500VZE:
+       case FAMILY_1500VZF:
+               platform_features = FFS_CAPABLE;
+               asic = ASIC_CALLIOPE;
+               asic_phy_base = CALLIOPE_IO_BASE;
+               register_map = &calliope_register_map;
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+
+               if (platform_family == FAMILY_1500VZE) {
+                       gp_resources = non_dvr_vze_calliope_resources;
+                       pr_info("Platform: 1500/Vz Class E - "
+                               "CALLIOPE, NON_DVR_CAPABLE\n");
+               } else if (platform_family == FAMILY_1500VZF) {
+                       gp_resources = non_dvr_vzf_calliope_resources;
+                       pr_info("Platform: 1500/Vz Class F - "
+                               "CALLIOPE, NON_DVR_CAPABLE\n");
+               } else {
+                       gp_resources = non_dvr_calliope_resources;
+                       pr_info("Platform: 1500/RNG100 - CALLIOPE, "
+                               "NON_DVR_CAPABLE\n");
+               }
+               break;
+
+       case FAMILY_4500:
+               platform_features = FFS_CAPABLE | PCIE_CAPABLE |
+                       DISPLAY_CAPABLE;
+               asic = ASIC_ZEUS;
+               asic_phy_base = ZEUS_IO_BASE;
+               register_map = &zeus_register_map;
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+               gp_resources = non_dvr_zeus_resources;
+
+               pr_info("Platform: 4500 - ZEUS, NON_DVR_CAPABLE\n");
+               break;
+
+       case FAMILY_4600:
+       {
+               unsigned int chipversion = 0;
+
+               /* The settop has PCIE but it isn't used, so don't advertise
+                * it*/
+               platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
+               asic_phy_base = CRONUS_IO_BASE;   /* same as Cronus */
+               register_map = &cronus_register_map;   /* same as Cronus */
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+               gp_resources = non_dvr_cronuslite_resources;
+
+               /* ASIC version will determine if this is a real CronusLite or
+                * Castrati(Cronus) */
+               chipversion  = asic_read(chipver3) << 24;
+               chipversion |= asic_read(chipver2) << 16;
+               chipversion |= asic_read(chipver1) << 8;
+               chipversion |= asic_read(chipver0);
+
+               if ((chipversion == CRONUS_10) || (chipversion == CRONUS_11))
+                       asic = ASIC_CRONUS;
+               else
+                       asic = ASIC_CRONUSLITE;
+
+               pr_info("Platform: 4600 - %s, NON_DVR_CAPABLE, "
+                       "chipversion=0x%08X\n",
+                       (asic == ASIC_CRONUS) ? "CRONUS" : "CRONUS LITE",
+                       chipversion);
+               break;
+       }
+       case FAMILY_4600VZA:
+               platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
+               asic = ASIC_CRONUS;
+               asic_phy_base = CRONUS_IO_BASE;
+               register_map = &cronus_register_map;
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+               gp_resources = non_dvr_cronus_resources;
+
+               pr_info("Platform: Vz Class A - CRONUS, NON_DVR_CAPABLE\n");
+               break;
+
+       case FAMILY_8500:
+       case FAMILY_8500RNG:
+               platform_features = DVR_CAPABLE | PCIE_CAPABLE |
+                       DISPLAY_CAPABLE;
+               asic = ASIC_ZEUS;
+               asic_phy_base = ZEUS_IO_BASE;
+               register_map = &zeus_register_map;
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+               gp_resources = dvr_zeus_resources;
+
+               pr_info("Platform: 8500/RNG200 - ZEUS, DVR_CAPABLE\n");
+               break;
+
+       case FAMILY_8600:
+       case FAMILY_8600VZB:
+               platform_features = DVR_CAPABLE | PCIE_CAPABLE |
+                       DISPLAY_CAPABLE;
+               asic = ASIC_CRONUS;
+               asic_phy_base = CRONUS_IO_BASE;
+               register_map = &cronus_register_map;
+               asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+                       ASIC_IO_SIZE);
+               gp_resources = dvr_cronus_resources;
+
+               pr_info("Platform: 8600/Vz Class B - CRONUS, "
+                       "DVR_CAPABLE\n");
+               break;
+
+       default:
+               pr_crit("Platform:  UNKNOWN PLATFORM\n");
+               break;
+       }
+
+       switch (asic) {
+       case ASIC_ZEUS:
+               phys_to_bus_offset = 0x30000000;
+               break;
+       case ASIC_CALLIOPE:
+               phys_to_bus_offset = 0x10000000;
+               break;
+       case ASIC_CRONUSLITE:
+               /* Fall through */
+       case ASIC_CRONUS:
+               /*
+                * TODO: We suppose 0x10000000 aliases into 0x20000000-
+                * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
+                * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
+                */
+               phys_to_bus_offset = 0x10000000;
+               break;
+       default:
+               phys_to_bus_offset = 0x00000000;
+               break;
+       }
+}
+
+/**
+ * platform_devices_init - sets up USB device resourse.
+ */
+static int __init platform_devices_init(void)
+{
+       pr_notice("%s: ----- Initializing USB resources -----\n", __func__);
+
+       asic_resource.start = asic_phy_base;
+       asic_resource.end += asic_resource.start;
+
+       ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase);
+       ehci_resources[0].end += ehci_resources[0].start;
+
+       ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision);
+       ohci_resources[0].end += ohci_resources[0].start;
+
+       set_io_port_base(0);
+
+       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+       return 0;
+}
+
+arch_initcall(platform_devices_init);
+
+/*
+ *
+ * BOOTMEM ALLOCATION
+ *
+ */
+/*
+ * Allocates/reserves the Platform memory resources early in the boot process.
+ * This ignores any resources that are designated IORESOURCE_IO
+ */
+void __init platform_alloc_bootmem(void)
+{
+       int i;
+       int total = 0;
+
+       /* Get persistent memory data from command line before allocating
+        * resources. This need to happen before normal command line parsing
+        * has been done */
+       pmem_setup_resource();
+
+       /* Loop through looking for resources that want a particular address */
+       for (i = 0; gp_resources[i].flags != 0; i++) {
+               int size = gp_resources[i].end - gp_resources[i].start + 1;
+               if ((gp_resources[i].start != 0) &&
+                       ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
+                       reserve_bootmem(bus_to_phys(gp_resources[i].start),
+                               size, 0);
+                       total += gp_resources[i].end -
+                               gp_resources[i].start + 1;
+                       pr_info("reserve resource %s at %08x (%u bytes)\n",
+                               gp_resources[i].name, gp_resources[i].start,
+                               gp_resources[i].end -
+                                       gp_resources[i].start + 1);
+               }
+       }
+
+       /* Loop through assigning addresses for those that are left */
+       for (i = 0; gp_resources[i].flags != 0; i++) {
+               int size = gp_resources[i].end - gp_resources[i].start + 1;
+               if ((gp_resources[i].start == 0) &&
+                       ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
+                       void *mem = alloc_bootmem_pages(size);
+
+                       if (mem == NULL)
+                               pr_err("Unable to allocate bootmem pages "
+                                       "for %s\n", gp_resources[i].name);
+
+                       else {
+                               gp_resources[i].start =
+                                       phys_to_bus(virt_to_phys(mem));
+                               gp_resources[i].end =
+                                       gp_resources[i].start + size - 1;
+                               total += size;
+                               pr_info("allocate resource %s at %08x "
+                                               "(%u bytes)\n",
+                                       gp_resources[i].name,
+                                       gp_resources[i].start, size);
+                       }
+               }
+       }
+
+       pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
+
+       /* indicate resources that are platform I/O related */
+       for (i = 0; gp_resources[i].flags != 0; i++) {
+               if ((gp_resources[i].start != 0) &&
+                       ((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
+                       pr_info("reserved platform resource %s at %08x\n",
+                               gp_resources[i].name, gp_resources[i].start);
+               }
+       }
+}
+
+/*
+ *
+ * PERSISTENT MEMORY (PMEM) CONFIGURATION
+ *
+ */
+static unsigned long pmemaddr __initdata;
+
+static int __init early_param_pmemaddr(char *p)
+{
+       pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
+       return 0;
+}
+early_param("pmemaddr", early_param_pmemaddr);
+
+static long pmemlen __initdata;
+
+static int __init early_param_pmemlen(char *p)
+{
+/* TODO: we can use this code when and if the bootloader ever changes this */
+#if 0
+       pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
+#else
+       pmemlen = 0x20000;
+#endif
+       return 0;
+}
+early_param("pmemlen", early_param_pmemlen);
+
+/*
+ * Set up persistent memory. If we were given values, we patch the array of
+ * resources. Otherwise, persistent memory may be allocated anywhere at all.
+ */
+static void __init pmem_setup_resource(void)
+{
+       struct resource *resource;
+       resource = asic_resource_get("DiagPersistentMemory");
+
+       if (resource && pmemaddr && pmemlen) {
+               /* The address provided by bootloader is in kseg0. Convert to
+                * a bus address. */
+               resource->start = phys_to_bus(pmemaddr - 0x80000000);
+               resource->end = resource->start + pmemlen - 1;
+
+               pr_info("persistent memory: start=0x%x  end=0x%x\n",
+                       resource->start, resource->end);
+       }
+}
+
+/*
+ *
+ * RESOURCE ACCESS FUNCTIONS
+ *
+ */
+
+/**
+ * asic_resource_get - retrieves parameters for a platform resource.
+ * @name:      string to match resource
+ *
+ * Returns a pointer to a struct resource corresponding to the given name.
+ *
+ * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
+ * as this function name is already declared
+ */
+struct resource *asic_resource_get(const char *name)
+{
+       int i;
+
+       for (i = 0; gp_resources[i].flags != 0; i++) {
+               if (strcmp(gp_resources[i].name, name) == 0)
+                       return &gp_resources[i];
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(asic_resource_get);
+
+/**
+ * platform_release_memory - release pre-allocated memory
+ * @ptr:       pointer to memory to release
+ * @size:      size of resource
+ *
+ * This must only be called for memory allocated or reserved via the boot
+ * memory allocator.
+ */
+void platform_release_memory(void *ptr, int size)
+{
+       unsigned long addr;
+       unsigned long end;
+
+       addr = ((unsigned long)ptr + (PAGE_SIZE - 1)) & PAGE_MASK;
+       end = ((unsigned long)ptr + size) & PAGE_MASK;
+
+       for (; addr < end; addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(__va(addr)));
+               init_page_count(virt_to_page(__va(addr)));
+               free_page((unsigned long)__va(addr));
+       }
+}
+EXPORT_SYMBOL(platform_release_memory);
+
+/*
+ *
+ * FEATURE AVAILABILITY FUNCTIONS
+ *
+ */
+int platform_supports_dvr(void)
+{
+       return (platform_features & DVR_CAPABLE) != 0;
+}
+
+int platform_supports_ffs(void)
+{
+       return (platform_features & FFS_CAPABLE) != 0;
+}
+
+int platform_supports_pcie(void)
+{
+       return (platform_features & PCIE_CAPABLE) != 0;
+}
+
+int platform_supports_display(void)
+{
+       return (platform_features & DISPLAY_CAPABLE) != 0;
+}
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
new file mode 100644 (file)
index 0000000..80b2eed
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ * Portions copyright (C) 2009  Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the PowerTV
+ * platform.
+ *
+ * The interrupt controller is located in the South Bridge a PIIX4 device
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+
+#include <asm/irq_cpu.h>
+#include <linux/io.h>
+#include <asm/irq_regs.h>
+#include <asm/mips-boards/generic.h>
+
+#include <asm/mach-powertv/asic_regs.h>
+
+static DEFINE_SPINLOCK(asic_irq_lock);
+
+static inline int get_int(void)
+{
+       unsigned long flags;
+       int irq;
+
+       spin_lock_irqsave(&asic_irq_lock, flags);
+
+       irq = (asic_read(int_int_scan) >> 4) - 1;
+
+       if (irq == 0 || irq >= NR_IRQS)
+               irq = -1;
+
+       spin_unlock_irqrestore(&asic_irq_lock, flags);
+
+       return irq;
+}
+
+static void asic_irqdispatch(void)
+{
+       int irq;
+
+       irq = get_int();
+       if (irq < 0)
+               return;  /* interrupt has already been cleared */
+
+       do_IRQ(irq);
+}
+
+static inline int clz(unsigned long x)
+{
+       __asm__(
+       "       .set    push                                    \n"
+       "       .set    mips32                                  \n"
+       "       clz     %0, %1                                  \n"
+       "       .set    pop                                     \n"
+       : "=r" (x)
+       : "r" (x));
+
+       return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+       return fls(pending) - 1 + CAUSEB_IP;
+}
+
+/*
+ * TODO: check how it works under EIC mode.
+ */
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       int irq;
+
+       irq = irq_ffs(pending);
+
+       if (irq == CAUSEF_IP3)
+               asic_irqdispatch();
+       else if (irq >= 0)
+               do_IRQ(irq);
+       else
+               spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+       int i;
+
+       asic_irq_init();
+
+       /*
+        * Initialize interrupt exception vectors.
+        */
+       if (cpu_has_veic || cpu_has_vint) {
+               int nvec = cpu_has_veic ? 64 : 8;
+               for (i = 0; i < nvec; i++)
+                       set_vi_handler(i, asic_irqdispatch);
+       }
+}
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
new file mode 100644 (file)
index 0000000..b54d244
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Portions copyright (C) 2005-2009 Scientific Atlanta
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ * Modified from arch/mips/kernel/irq-rm7000.c:
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/mach-powertv/asic_regs.h>
+
+static inline void unmask_asic_irq(unsigned int irq)
+{
+       unsigned long enable_bit;
+
+       enable_bit = (1 << (irq & 0x1f));
+
+       switch (irq >> 5) {
+       case 0:
+               asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
+               break;
+       case 1:
+               asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
+               break;
+       case 2:
+               asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
+               break;
+       case 3:
+               asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void mask_asic_irq(unsigned int irq)
+{
+       unsigned long disable_mask;
+
+       disable_mask = ~(1 << (irq & 0x1f));
+
+       switch (irq >> 5) {
+       case 0:
+               asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
+               break;
+       case 1:
+               asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
+               break;
+       case 2:
+               asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
+               break;
+       case 3:
+               asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static struct irq_chip asic_irq_chip = {
+       .name = "ASIC Level",
+       .ack = mask_asic_irq,
+       .mask = mask_asic_irq,
+       .mask_ack = mask_asic_irq,
+       .unmask = unmask_asic_irq,
+       .eoi = unmask_asic_irq,
+};
+
+void __init asic_irq_init(void)
+{
+       int i;
+
+       /* set priority to 0 */
+       write_c0_status(read_c0_status() & ~(0x0000fc00));
+
+       asic_write(0, ien_int_0);
+       asic_write(0, ien_int_1);
+       asic_write(0, ien_int_2);
+       asic_write(0, ien_int_3);
+
+       asic_write(0x0fffffff, int_level_3_3);
+       asic_write(0xffffffff, int_level_3_2);
+       asic_write(0xffffffff, int_level_3_1);
+       asic_write(0xffffffff, int_level_3_0);
+       asic_write(0xffffffff, int_level_2_3);
+       asic_write(0xffffffff, int_level_2_2);
+       asic_write(0xffffffff, int_level_2_1);
+       asic_write(0xffffffff, int_level_2_0);
+       asic_write(0xffffffff, int_level_1_3);
+       asic_write(0xffffffff, int_level_1_2);
+       asic_write(0xffffffff, int_level_1_1);
+       asic_write(0xffffffff, int_level_1_0);
+       asic_write(0xffffffff, int_level_0_3);
+       asic_write(0xffffffff, int_level_0_2);
+       asic_write(0xffffffff, int_level_0_1);
+       asic_write(0xffffffff, int_level_0_0);
+
+       asic_write(0xf, int_int_scan);
+
+       /*
+        * Initialize interrupt handlers.
+        */
+       for (i = 0; i < NR_IRQS; i++)
+               set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
+}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
new file mode 100644 (file)
index 0000000..cd5b76a
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Memory pre-allocations for Calliope boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * NON_DVR_CAPABLE CALLIOPE RESOURCES
+ */
+struct resource non_dvr_calliope_resources[] __initdata =
+{
+       /*
+        * VIDEO / LX1
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x24000000,
+               .end    = 0x24200000 - 1,       /*2MiB */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",   /*8KiB block ST231a monitor */
+               .start  = 0x24200000,
+               .end    = 0x24202000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x24202000,
+               .end    = 0x26700000 - 1, /*~36.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Sysaudio Driver
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * STAVEM driver/STAPI
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x00000000,
+               .end    = 0x00600000 - 1,       /* 6 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DOCSIS Subsystem
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x22000000,
+               .end    = 0x22700000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * GHW HAL Driver
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x22700000,
+               .end    = 0x23500000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * multi com buffer area
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x23700000,
+               .end    = 0x23720000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DMA Ring buffer (don't need recording buffers)
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit0
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,           /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * AVFS: player HAL memory
+        *
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x00000000,
+               .end    = 0x002c4c00 - 1,       /* 945K * 3 for playback */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * PMEM
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Smartcard
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE + 0x400 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Synopsys GMAC Memory Region
+        */
+       {
+               .name   = "GMAC",
+               .start  = 0x00000000,
+               .end    = 0x00010000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Add other resources here
+        *
+        */
+       { },
+};
+
+struct resource non_dvr_vz_calliope_resources[] __initdata =
+{
+       /*
+        * VIDEO / LX1
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x24000000,
+               .end    = 0x24200000 - 1, /*2 Meg */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8k block ST231a monitor */
+               .start  = 0x24200000,
+               .end    = 0x24202000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x22202000,
+               .end    = 0x22C20B85 - 1,       /* 10.12 Meg */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Sysaudio Driver
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * STAVEM driver/STAPI
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x20300000,
+               .end    = 0x20620000-1,  /*3.125 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * GHW HAL Driver
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x20100000,
+               .end    = 0x20300000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * multi com buffer area
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x23900000,
+               .end    = 0x23920000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DMA Ring buffer
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit0
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * PMEM
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Smartcard
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE+0x400 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Synopsys GMAC Memory Region
+        */
+       {
+               .name   = "GMAC",
+               .start  = 0x00000000,
+               .end    = 0x00010000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
+
+struct resource non_dvr_vze_calliope_resources[] __initdata =
+{
+       /*
+        * VIDEO / LX1
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x22000000,
+               .end    = 0x22200000 - 1,       /*2  Meg */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8k block ST231a monitor */
+               .start  = 0x22200000,
+               .end    = 0x22202000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x22202000,
+               .end    = 0x22C20B85 - 1,       /* 10.12 Meg */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Sysaudio Driver
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * STAVEM driver/STAPI
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x20396000,
+               .end    = 0x206B6000 - 1,               /* 3.125 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * GHW HAL Driver
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x20100000,
+               .end    = 0x20396000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * multi com buffer area
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x206B6000,
+               .end    = 0x206D6000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DMA Ring buffer
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit0
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * PMEM
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Smartcard
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE+0x400 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Synopsys GMAC Memory Region
+        */
+       {
+               .name   = "GMAC",
+               .start  = 0x00000000,
+               .end    = 0x00010000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
+
+struct resource non_dvr_vzf_calliope_resources[] __initdata =
+{
+       /*
+        * VIDEO / LX1
+        */
+       {
+               .name   = "ST231aImage",        /*Delta-Mu 1 image and ram */
+               .start  = 0x24000000,
+               .end    = 0x24200000 - 1,       /*2MiB */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",      /*8KiB block ST231a monitor */
+               .start  = 0x24200000,
+               .end    = 0x24202000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x24202000,
+               /* ~19.4 (21.5MiB - (2MiB + 8KiB)) */
+               .end    = 0x25580000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Sysaudio Driver
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * STAVEM driver/STAPI
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x00000000,
+               .end    = 0x00480000 - 1,  /* 4.5 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * GHW HAL Driver
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x22700000,
+               .end    = 0x23500000 - 1, /* 14 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * multi com buffer area
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x23700000,
+               .end    = 0x23720000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DMA Ring buffer (don't need recording buffers)
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit0
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,  /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit1
+        */
+       {
+               .name   = "DisplayBins1",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,  /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * AVFS: player HAL memory
+        *
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x00000000,
+               .end    = 0x002c4c00 - 1,  /* 945K * 3 for playback */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * PMEM
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Smartcard
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE + 0x400 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Synopsys GMAC Memory Region
+        */
+       {
+               .name   = "GMAC",
+               .start  = 0x00000000,
+               .end    = 0x00010000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
new file mode 100644 (file)
index 0000000..45a5c3e
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Memory pre-allocations for Cronus boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * DVR_CAPABLE CRONUS RESOURCES
+ */
+struct resource dvr_cronus_resources[] __initdata =
+{
+       /*
+        *
+        * VIDEO1 / LX1
+        *
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x24000000,
+               .end    = 0x241FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8KiB block ST231a monitor */
+               .start  = 0x24200000,
+               .end    = 0x24201FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x24202000,
+               .end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * VIDEO2 / LX2
+        *
+        */
+       {
+               .name   = "ST231bImage",        /* Delta-Mu 2 image and ram */
+               .start  = 0x60000000,
+               .end    = 0x601FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231bMonitor",      /* 8KiB block ST231b monitor */
+               .start  = 0x60200000,
+               .end    = 0x60201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory2",
+               .start  = 0x60202000,
+               .end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * Sysaudio Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  DSP_Image_Buff - DSP code and data images (1MB)
+        *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+        *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+        *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+        *
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * STAVEM driver/STAPI
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  This memory area is used for allocating buffers for Video decoding
+        *  purposes.  Allocation/De-allocation within this buffer is managed
+        *  by the STAVMEM driver of the STAPI.  They could be Decimated
+        *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+        *  video decoding purposes, for any video decoders on Zeus.
+        *
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x63580000,
+               .end    = 0x64180000 - 1,  /* 12 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * DOCSIS Subsystem
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x62000000,
+               .end    = 0x62700000 - 1,       /* 7 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * GHW HAL Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  GraphicsHeap - PowerTV Graphics Heap
+        *
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x62700000,
+               .end    = 0x63500000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * multi com buffer area
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x26000000,
+               .end    = 0x26020000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * DMA Ring buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x00280000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer for unit0
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit0
+        *
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,           /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit1
+        *
+        */
+       {
+               .name   = "DisplayBins1",
+               .start  = 0x64AD4000,
+               .end    = 0x64AD5000 - 1,  /* 4 KB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * ITFS
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "ITFS",
+               .start  = 0x64180000,
+               /* 815,104 bytes each for 2 ITFS partitions. */
+               .end    = 0x6430DFFF,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * AVFS
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x6430E000,
+               /* (945K * 8) = (128K *3) 5 playbacks / 3 server */
+               .end    = 0x64AD0000 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "AvfsFileSys",
+               .start  = 0x64AD0000,
+               .end    = 0x64AD1000 - 1,  /* 4K */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * PMEM
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Persistent memory for diagnostics.
+        *
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Smartcard
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Read and write buffers for Internal/External cards
+        *
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x64AD1000,
+               .end    = 0x64AD3800 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * KAVNET
+        *    NP Reset Vector - must be of the form xxCxxxxx
+        *         NP Image - must be video bank 1
+        *         NP IPC - must be video bank 2
+        */
+       {
+               .name   = "NP_Reset_Vector",
+               .start  = 0x27c00000,
+               .end    = 0x27c01000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_Image",
+               .start  = 0x27020000,
+               .end    = 0x27060000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_IPC",
+               .start  = 0x63500000,
+               .end    = 0x63580000 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
+
+/*
+ * NON_DVR_CAPABLE CRONUS RESOURCES
+ */
+struct resource non_dvr_cronus_resources[] __initdata =
+{
+       /*
+        *
+        * VIDEO1 / LX1
+        *
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x24000000,
+               .end    = 0x241FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8KiB block ST231a monitor */
+               .start  = 0x24200000,
+               .end    = 0x24201FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x24202000,
+               .end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * VIDEO2 / LX2
+        *
+        */
+       {
+               .name   = "ST231bImage",        /* Delta-Mu 2 image and ram */
+               .start  = 0x60000000,
+               .end    = 0x601FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231bMonitor",      /* 8KiB block ST231b monitor */
+               .start  = 0x60200000,
+               .end    = 0x60201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory2",
+               .start  = 0x60202000,
+               .end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * Sysaudio Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  DSP_Image_Buff - DSP code and data images (1MB)
+        *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+        *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+        *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+        *
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * STAVEM driver/STAPI
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  This memory area is used for allocating buffers for Video decoding
+        *  purposes.  Allocation/De-allocation within this buffer is managed
+        *  by the STAVMEM driver of the STAPI.  They could be Decimated
+        *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+        *  video decoding purposes, for any video decoders on Zeus.
+        *
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x63580000,
+               .end    = 0x64180000 - 1,  /* 12 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * DOCSIS Subsystem
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x62000000,
+               .end    = 0x62700000 - 1,       /* 7 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * GHW HAL Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  GraphicsHeap - PowerTV Graphics Heap
+        *
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x62700000,
+               .end    = 0x63500000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * multi com buffer area
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x26000000,
+               .end    = 0x26020000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * DMA Ring buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer for unit0
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit0
+        *
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,           /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit1
+        *
+        */
+       {
+               .name   = "DisplayBins1",
+               .start  = 0x64AD4000,
+               .end    = 0x64AD5000 - 1,  /* 4 KB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * AVFS: player HAL memory
+        *
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x6430E000,
+               .end    = 0x645D2C00 - 1,  /* 945K * 3 for playback */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * PMEM
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Persistent memory for diagnostics.
+        *
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Smartcard
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Read and write buffers for Internal/External cards
+        *
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x64AD1000,
+               .end    = 0x64AD3800 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * KAVNET
+        *    NP Reset Vector - must be of the form xxCxxxxx
+        *         NP Image - must be video bank 1
+        *         NP IPC - must be video bank 2
+        */
+       {
+               .name   = "NP_Reset_Vector",
+               .start  = 0x27c00000,
+               .end    = 0x27c01000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_Image",
+               .start  = 0x27020000,
+               .end    = 0x27060000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_IPC",
+               .start  = 0x63500000,
+               .end    = 0x63580000 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       { },
+};
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
new file mode 100644 (file)
index 0000000..23a9056
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Memory pre-allocations for Cronus Lite boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * NON_DVR_CAPABLE CRONUSLITE RESOURCES
+ */
+struct resource non_dvr_cronuslite_resources[] __initdata =
+{
+       /*
+        *
+        * VIDEO2 / LX2
+        *
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 2 image and ram */
+               .start  = 0x60000000,
+               .end    = 0x601FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8KiB block ST231b monitor */
+               .start  = 0x60200000,
+               .end    = 0x60201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x60202000,
+               .end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * Sysaudio Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  DSP_Image_Buff - DSP code and data images (1MB)
+        *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+        *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+        *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+        *
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * STAVEM driver/STAPI
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  This memory area is used for allocating buffers for Video decoding
+        *  purposes.  Allocation/De-allocation within this buffer is managed
+        *  by the STAVMEM driver of the STAPI.  They could be Decimated
+        *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+        *  video decoding purposes, for any video decoders on Zeus.
+        *
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x63580000,
+               .end    = 0x63B80000 - 1,  /* 6 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * DOCSIS Subsystem
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x62000000,
+               .end    = 0x62700000 - 1,       /* 7 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * GHW HAL Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  GraphicsHeap - PowerTV Graphics Heap
+        *
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x62700000,
+               .end    = 0x63500000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * multi com buffer area
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x26000000,
+               .end    = 0x26020000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * DMA Ring buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x000AA000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer for unit0
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit0
+        *
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,           /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit1
+        *
+        */
+       {
+               .name   = "DisplayBins1",
+               .start  = 0x63B83000,
+               .end    = 0x63B84000 - 1,  /* 4 KB total */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * AVFS: player HAL memory
+        *
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x63B84000,
+               .end    = 0x63E48C00 - 1,  /* 945K * 3 for playback */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * PMEM
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Persistent memory for diagnostics.
+        *
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Smartcard
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Read and write buffers for Internal/External cards
+        *
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x63B80000,
+               .end    = 0x63B82800 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * KAVNET
+        *    NP Reset Vector - must be of the form xxCxxxxx
+        *         NP Image - must be video bank 1
+        *         NP IPC - must be video bank 2
+        */
+       {
+               .name   = "NP_Reset_Vector",
+               .start  = 0x27c00000,
+               .end    = 0x27c01000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_Image",
+               .start  = 0x27020000,
+               .end    = 0x27060000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "NP_IPC",
+               .start  = 0x63500000,
+               .end    = 0x63580000 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE + 0x400 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
new file mode 100644 (file)
index 0000000..018d451
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Memory pre-allocations for Zeus boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * DVR_CAPABLE RESOURCES
+ */
+struct resource dvr_zeus_resources[] __initdata =
+{
+       /*
+        *
+        * VIDEO1 / LX1
+        *
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x20000000,
+               .end    = 0x201FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8KiB block ST231a monitor */
+               .start  = 0x20200000,
+               .end    = 0x20201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x20202000,
+               .end    = 0x21FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * VIDEO2 / LX2
+        *
+        */
+       {
+               .name   = "ST231bImage",        /* Delta-Mu 2 image and ram */
+               .start  = 0x30000000,
+               .end    = 0x301FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231bMonitor",      /* 8KiB block ST231b monitor */
+               .start  = 0x30200000,
+               .end    = 0x30201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory2",
+               .start  = 0x30202000,
+               .end    = 0x31FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        *
+        * Sysaudio Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  DSP_Image_Buff - DSP code and data images (1MB)
+        *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+        *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+        *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+        *
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * STAVEM driver/STAPI
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  This memory area is used for allocating buffers for Video decoding
+        *  purposes.  Allocation/De-allocation within this buffer is managed
+        *  by the STAVMEM driver of the STAPI.  They could be Decimated
+        *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+        *  video decoding purposes, for any video decoders on Zeus.
+        *
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x00000000,
+               .end    = 0x00c00000 - 1,       /* 12 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * DOCSIS Subsystem
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x40100000,
+               .end    = 0x407fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * GHW HAL Driver
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  GraphicsHeap - PowerTV Graphics Heap
+        *
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x46900000,
+               .end    = 0x47700000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * multi com buffer area
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x47900000,
+               .end    = 0x47920000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * DMA Ring buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x00280000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer for unit0
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit0
+        *
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,   /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Display bins buffer
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Display Bins for unit1
+        *
+        */
+       {
+               .name   = "DisplayBins1",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,   /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * ITFS
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "ITFS",
+               .start  = 0x00000000,
+               /* 815,104 bytes each for 2 ITFS partitions. */
+               .end    = 0x0018DFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * AVFS
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Docsis -
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x00000000,
+               /* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
+               .end    = 0x007c2000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "AvfsFileSys",
+               .start  = 0x00000000,
+               .end    = 0x00001000 - 1,  /* 4K */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * PMEM
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Persistent memory for diagnostics.
+        *
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * Smartcard
+        *
+        * This driver requires:
+        *
+        * Arbitrary Based Buffers:
+        *  Read and write buffers for Internal/External cards
+        *
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
+
+/*
+ * NON_DVR_CAPABLE ZEUS RESOURCES
+ */
+struct resource non_dvr_zeus_resources[] __initdata =
+{
+       /*
+        * VIDEO1 / LX1
+        */
+       {
+               .name   = "ST231aImage",        /* Delta-Mu 1 image and ram */
+               .start  = 0x20000000,
+               .end    = 0x201FFFFF,           /* 2MiB */
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "ST231aMonitor",      /* 8KiB block ST231a monitor */
+               .start  = 0x20200000,
+               .end    = 0x20201FFF,
+               .flags  = IORESOURCE_IO,
+       },
+       {
+               .name   = "MediaMemory1",
+               .start  = 0x20202000,
+               .end    = 0x21FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Sysaudio Driver
+        */
+       {
+               .name   = "DSP_Image_Buff",
+               .start  = 0x00000000,
+               .end    = 0x000FFFFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_CPU_PCM_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00009FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_AUX_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "ADSC_Main_Buff",
+               .start  = 0x00000000,
+               .end    = 0x00003FFF,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * STAVEM driver/STAPI
+        */
+       {
+               .name   = "AVMEMPartition0",
+               .start  = 0x00000000,
+               .end    = 0x00600000 - 1,       /* 6 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DOCSIS Subsystem
+        */
+       {
+               .name   = "Docsis",
+               .start  = 0x40100000,
+               .end    = 0x407fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * GHW HAL Driver
+        */
+       {
+               .name   = "GraphicsHeap",
+               .start  = 0x46900000,
+               .end    = 0x47700000 - 1,       /* 14 MB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * multi com buffer area
+        */
+       {
+               .name   = "MulticomSHM",
+               .start  = 0x47900000,
+               .end    = 0x47920000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * DMA Ring buffer
+        */
+       {
+               .name   = "BMM_Buffer",
+               .start  = 0x00000000,
+               .end    = 0x00280000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Display bins buffer for unit0
+        */
+       {
+               .name   = "DisplayBins0",
+               .start  = 0x00000000,
+               .end    = 0x00000FFF,           /* 4 KB total */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        *
+        * AVFS: player HAL memory
+        *
+        *
+        */
+       {
+               .name   = "AvfsDmaMem",
+               .start  = 0x00000000,
+               .end    = 0x002c4c00 - 1,       /* 945K * 3 for playback */
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * PMEM
+        */
+       {
+               .name   = "DiagPersistentMemory",
+               .start  = 0x00000000,
+               .end    = 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * Smartcard
+        */
+       {
+               .name   = "SmartCardInfo",
+               .start  = 0x00000000,
+               .end    = 0x2800 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /*
+        * NAND Flash
+        */
+       {
+               .name   = "NandFlash",
+               .start  = NAND_FLASH_BASE,
+               .end    = NAND_FLASH_BASE + 0x400 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       /*
+        * Add other resources here
+        */
+       { },
+};
diff --git a/arch/mips/powertv/cmdline.c b/arch/mips/powertv/cmdline.c
new file mode 100644 (file)
index 0000000..98d73cb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "init.h"
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+void  __init prom_init_cmdline(void)
+{
+       int len;
+
+       if (prom_argc != 1)
+               return;
+
+       len = strlen(arcs_cmdline);
+
+       arcs_cmdline[len] = ' ';
+
+       strlcpy(arcs_cmdline + len + 1, (char *)_prom_argv,
+               COMMAND_LINE_SIZE - len - 1);
+}
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
new file mode 100644 (file)
index 0000000..5f4e4c3
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
+ *     All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/bootinfo.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mach-powertv/asic.h>
+
+#include "init.h"
+
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+unsigned long _prom_memsize;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
+
+char *prom_getenv(char *envname)
+{
+       char *result = NULL;
+
+       if (_prom_envp != NULL) {
+               /*
+                * Return a pointer to the given environment variable.
+                * In 64-bit mode: we're using 64-bit pointers, but all pointers
+                * in the PROM structures are only 32-bit, so we need some
+                * workarounds, if we are running in 64-bit mode.
+                */
+               int i, index = 0;
+
+               i = strlen(envname);
+
+               while (prom_envp(index)) {
+                       if (strncmp(envname, prom_envp(index), i) == 0) {
+                               result = prom_envp(index + 1);
+                               break;
+                       }
+                       index += 2;
+               }
+       }
+
+       return result;
+}
+
+/* TODO: Verify on linux-mips mailing list that the following two  */
+/* functions are correct                                           */
+/* TODO: Copy NMI and EJTAG exception vectors to memory from the   */
+/* BootROM exception vectors. Flush their cache entries. test it.  */
+
+static void __init mips_nmi_setup(void)
+{
+       void *base;
+#if defined(CONFIG_CPU_MIPS32_R1)
+       base = cpu_has_veic ?
+               (void *)(CAC_BASE + 0xa80) :
+               (void *)(CAC_BASE + 0x380);
+#elif defined(CONFIG_CPU_MIPS32_R2)
+       base = (void *)0xbfc00000;
+#else
+#error NMI exception handler address not defined
+#endif
+}
+
+static void __init mips_ejtag_setup(void)
+{
+       void *base;
+
+#if defined(CONFIG_CPU_MIPS32_R1)
+       base = cpu_has_veic ?
+               (void *)(CAC_BASE + 0xa00) :
+               (void *)(CAC_BASE + 0x300);
+#elif defined(CONFIG_CPU_MIPS32_R2)
+       base = (void *)0xbfc00480;
+#else
+#error EJTAG exception handler address not defined
+#endif
+}
+
+void __init prom_init(void)
+{
+       prom_argc = fw_arg0;
+       _prom_argv = (int *) fw_arg1;
+       _prom_envp = (int *) fw_arg2;
+       _prom_memsize = (unsigned long) fw_arg3;
+
+       board_nmi_handler_setup = mips_nmi_setup;
+       board_ejtag_handler_setup = mips_ejtag_setup;
+
+       pr_info("\nLINUX started...\n");
+       prom_init_cmdline();
+       configure_platform();
+       prom_meminit();
+
+#ifndef CONFIG_BOOTLOADER_DRIVER
+       pr_info("\nBootloader driver isn't loaded...\n");
+#endif
+}
diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h
new file mode 100644 (file)
index 0000000..7af6bf2
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Definitions from powertv init.c file
+ *
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_INIT_H
+#define _POWERTV_INIT_H
+extern int prom_argc;
+extern int *_prom_argv;
+extern unsigned long _prom_memsize;
+#endif
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
new file mode 100644 (file)
index 0000000..28d0660
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Apparently originally from arch/mips/malta-memory.c. Modified to work
+ * with the PowerTV bootloader.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mips-boards/prom.h>
+
+#include "init.h"
+
+/* Memory constants */
+#define KIBIBYTE(n)            ((n) * 1024)    /* Number of kibibytes */
+#define MEBIBYTE(n)            ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
+#define DEFAULT_MEMSIZE                MEBIBYTE(256)   /* If no memsize provided */
+#define LOW_MEM_MAX            MEBIBYTE(252)   /* Max usable low mem */
+#define RES_BOOTLDR_MEMSIZE    MEBIBYTE(1)     /* Memory reserved for bldr */
+#define BOOT_MEM_SIZE          KIBIBYTE(256)   /* Memory reserved for bldr */
+#define PHYS_MEM_START         0x10000000      /* Start of physical memory */
+
+unsigned long ptv_memsize;
+
+char __initdata cmdline[COMMAND_LINE_SIZE];
+
+void __init prom_meminit(void)
+{
+       char *memsize_str;
+       unsigned long memsize = 0;
+       unsigned int physend;
+       char *ptr;
+       int low_mem;
+       int high_mem;
+
+       /* Check the command line first for a memsize directive */
+       strcpy(cmdline, arcs_cmdline);
+       ptr = strstr(cmdline, "memsize=");
+       if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
+               ptr = strstr(ptr, " memsize=");
+
+       if (ptr) {
+               memsize = memparse(ptr + 8, &ptr);
+       } else {
+               /* otherwise look in the environment */
+               memsize_str = prom_getenv("memsize");
+
+               if (memsize_str != NULL) {
+                       pr_info("prom memsize = %s\n", memsize_str);
+                       memsize = simple_strtol(memsize_str, NULL, 0);
+               }
+
+               if (memsize == 0) {
+                       if (_prom_memsize != 0) {
+                               memsize = _prom_memsize;
+                               pr_info("_prom_memsize = 0x%lx\n", memsize);
+                               /* add in memory that the bootloader doesn't
+                                * report */
+                               memsize += BOOT_MEM_SIZE;
+                       } else {
+                               memsize = DEFAULT_MEMSIZE;
+                               pr_info("Memsize not passed by bootloader, "
+                                       "defaulting to 0x%lx\n", memsize);
+                       }
+               }
+       }
+
+       /* Store memsize for diagnostic purposes */
+       ptv_memsize = memsize;
+
+       physend = PFN_ALIGN(&_end) - 0x80000000;
+       if (memsize > LOW_MEM_MAX) {
+               low_mem = LOW_MEM_MAX;
+               high_mem = memsize - low_mem;
+       } else {
+               low_mem = memsize;
+               high_mem = 0;
+       }
+
+/*
+ * TODO: We will use the hard code for memory configuration until
+ * the bootloader releases their device tree to us.
+ */
+       /*
+        * Add the memory reserved for use by the bootloader to the
+        * memory map.
+        */
+       add_memory_region(PHYS_MEM_START, RES_BOOTLDR_MEMSIZE,
+               BOOT_MEM_RESERVED);
+#ifdef CONFIG_HIGHMEM_256_128
+       /*
+        * Add memory in low for general use by the kernel and its friends
+        * (like drivers, applications, etc).
+        */
+       add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+               LOW_MEM_MAX - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+       /*
+        * Add the memory reserved for reset vector.
+        */
+       add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED);
+       /*
+        * Add the memory reserved.
+        */
+       add_memory_region(0x20000000, MEBIBYTE(1024 + 75), BOOT_MEM_RESERVED);
+       /*
+        * Add memory in high for general use by the kernel and its friends
+        * (like drivers, applications, etc).
+        *
+        * 75MB is reserved for devices which are using the memory in high.
+        */
+       add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75),
+               BOOT_MEM_RAM);
+#elif defined CONFIG_HIGHMEM_128_128
+       /*
+        * Add memory in low for general use by the kernel and its friends
+        * (like drivers, applications, etc).
+        */
+       add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+               MEBIBYTE(128) - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+       /*
+        * Add the memory reserved.
+        */
+       add_memory_region(PHYS_MEM_START + MEBIBYTE(128),
+               MEBIBYTE(128 + 1024 + 75), BOOT_MEM_RESERVED);
+       /*
+        * Add memory in high for general use by the kernel and its friends
+        * (like drivers, applications, etc).
+        *
+        * 75MB is reserved for devices which are using the memory in high.
+        */
+       add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75),
+               BOOT_MEM_RAM);
+#else
+       /* Add low memory regions for either:
+        *   - no-highmemory configuration case -OR-
+        *   - highmemory "HIGHMEM_LOWBANK_ONLY" case
+        */
+       /*
+        * Add memory for general use by the kernel and its friends
+        * (like drivers, applications, etc).
+        */
+       add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+               low_mem - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+       /*
+        * Add the memory reserved for reset vector.
+        */
+       add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED);
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+       unsigned long addr;
+       int i;
+
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+                       continue;
+
+               addr = boot_mem_map.map[i].addr;
+               free_init_pages("prom memory",
+                               addr, addr + boot_mem_map.map[i].size);
+       }
+}
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
new file mode 100644 (file)
index 0000000..f5c6246
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2009  Scientific-Atlanta, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This 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
+#
+
+obj-$(CONFIG_PCI)      += fixup-powertv.o
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/pci/fixup-powertv.c b/arch/mips/powertv/pci/fixup-powertv.c
new file mode 100644 (file)
index 0000000..726bc2e
--- /dev/null
@@ -0,0 +1,36 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mach-powertv/interrupts.h>
+#include "powertv-pci.h"
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return asic_pcie_map_irq(dev, slot, pin);
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
+
+/*
+ * asic_pcie_map_irq
+ *
+ * Parameters:
+ * *dev - pointer to a pci_dev structure  (not used)
+ * slot - slot number  (not used)
+ * pin - pin number  (not used)
+ *
+ * Return Value:
+ * Returns: IRQ number (always the PCI Express IRQ number)
+ *
+ * Description:
+ * asic_pcie_map_irq will return the IRQ number of the PCI Express interrupt.
+ *
+ */
+int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return irq_pciexp;
+}
+EXPORT_SYMBOL(asic_pcie_map_irq);
diff --git a/arch/mips/powertv/pci/powertv-pci.h b/arch/mips/powertv/pci/powertv-pci.h
new file mode 100644 (file)
index 0000000..1b5886b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *                             powertv-pci.c
+ *
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ */
+/*
+ * Local definitions for the powertv PCI code
+ */
+
+#ifndef _POWERTV_PCI_POWERTV_PCI_H_
+#define _POWERTV_PCI_POWERTV_PCI_H_
+extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+extern int asic_pcie_init(void);
+extern int asic_pcie_init(void);
+
+extern int log_level;
+#endif
diff --git a/arch/mips/powertv/powertv-clock.h b/arch/mips/powertv/powertv-clock.h
new file mode 100644 (file)
index 0000000..d94c543
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_POWERTV_CLOCK_H
+#define _POWERTV_POWERTV_CLOCK_H
+extern int powertv_clockevent_init(void);
+extern void powertv_clocksource_init(void);
+extern unsigned int mips_get_pll_freq(void);
+#endif
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
new file mode 100644 (file)
index 0000000..bd8ebf1
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/screen_info.h>
+#include <linux/notifier.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.h>
+
+#include <linux/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/dma.h>
+#include <linux/time.h>
+#include <asm/traps.h>
+#include <asm/asm-offsets.h>
+#include "reset.h"
+
+#define VAL(n)         STR(n)
+
+/*
+ * Macros for loading addresses and storing registers:
+ * PTR_LA      Load the address into a register
+ * LONG_S      Store the full width of the given register.
+ * LONG_L      Load the full width of the given register
+ * PTR_ADDIU   Add a constant value to a register used as a pointer
+ * REG_SIZE    Number of 8-bit bytes in a full width register
+ */
+#ifdef CONFIG_64BIT
+#warning TODO: 64-bit code needs to be verified
+#define PTR_LA         "dla    "
+#define LONG_S         "sd     "
+#define LONG_L         "ld     "
+#define PTR_ADDIU      "daddiu "
+#define REG_SIZE       "8"             /* In bytes */
+#endif
+
+#ifdef CONFIG_32BIT
+#define PTR_LA         "la     "
+#define LONG_S         "sw     "
+#define LONG_L         "lw     "
+#define PTR_ADDIU      "addiu  "
+#define REG_SIZE       "4"             /* In bytes */
+#endif
+
+static struct pt_regs die_regs;
+static bool have_die_regs;
+
+static void register_panic_notifier(void);
+static int panic_handler(struct notifier_block *notifier_block,
+       unsigned long event, void *cause_string);
+
+const char *get_system_type(void)
+{
+       return "PowerTV";
+}
+
+void __init plat_mem_setup(void)
+{
+       panic_on_oops = 1;
+       register_panic_notifier();
+
+#if 0
+       mips_pcibios_init();
+#endif
+       mips_reboot_setup();
+}
+
+/*
+ * Install a panic notifier for platform-specific diagnostics
+ */
+static void register_panic_notifier()
+{
+       static struct notifier_block panic_notifier = {
+               .notifier_call = panic_handler,
+               .next = NULL,
+               .priority       = INT_MAX
+       };
+       atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
+}
+
+static int panic_handler(struct notifier_block *notifier_block,
+       unsigned long event, void *cause_string)
+{
+       struct pt_regs  my_regs;
+
+       /* Save all of the registers */
+       {
+               unsigned long   at, v0, v1; /* Must be on the stack */
+
+               /* Start by saving $at and v0 on the stack. We use $at
+                * ourselves, but it looks like the compiler may use v0 or v1
+                * to load the address of the pt_regs structure. We'll come
+                * back later to store the registers in the pt_regs
+                * structure. */
+               __asm__ __volatile__ (
+                       ".set   noat\n"
+                       LONG_S          "$at, %[at]\n"
+                       LONG_S          "$2, %[v0]\n"
+                       LONG_S          "$3, %[v1]\n"
+               :
+                       [at] "=m" (at),
+                       [v0] "=m" (v0),
+                       [v1] "=m" (v1)
+               :
+               :       "at"
+               );
+
+               __asm__ __volatile__ (
+                       ".set   noat\n"
+                       "move           $at, %[pt_regs]\n"
+
+                       /* Argument registers */
+                       LONG_S          "$4, " VAL(PT_R4) "($at)\n"
+                       LONG_S          "$5, " VAL(PT_R5) "($at)\n"
+                       LONG_S          "$6, " VAL(PT_R6) "($at)\n"
+                       LONG_S          "$7, " VAL(PT_R7) "($at)\n"
+
+                       /* Temporary regs */
+                       LONG_S          "$8, " VAL(PT_R8) "($at)\n"
+                       LONG_S          "$9, " VAL(PT_R9) "($at)\n"
+                       LONG_S          "$10, " VAL(PT_R10) "($at)\n"
+                       LONG_S          "$11, " VAL(PT_R11) "($at)\n"
+                       LONG_S          "$12, " VAL(PT_R12) "($at)\n"
+                       LONG_S          "$13, " VAL(PT_R13) "($at)\n"
+                       LONG_S          "$14, " VAL(PT_R14) "($at)\n"
+                       LONG_S          "$15, " VAL(PT_R15) "($at)\n"
+
+                       /* "Saved" registers */
+                       LONG_S          "$16, " VAL(PT_R16) "($at)\n"
+                       LONG_S          "$17, " VAL(PT_R17) "($at)\n"
+                       LONG_S          "$18, " VAL(PT_R18) "($at)\n"
+                       LONG_S          "$19, " VAL(PT_R19) "($at)\n"
+                       LONG_S          "$20, " VAL(PT_R20) "($at)\n"
+                       LONG_S          "$21, " VAL(PT_R21) "($at)\n"
+                       LONG_S          "$22, " VAL(PT_R22) "($at)\n"
+                       LONG_S          "$23, " VAL(PT_R23) "($at)\n"
+
+                       /* Add'l temp regs */
+                       LONG_S          "$24, " VAL(PT_R24) "($at)\n"
+                       LONG_S          "$25, " VAL(PT_R25) "($at)\n"
+
+                       /* Kernel temp regs */
+                       LONG_S          "$26, " VAL(PT_R26) "($at)\n"
+                       LONG_S          "$27, " VAL(PT_R27) "($at)\n"
+
+                       /* Global pointer, stack pointer, frame pointer and
+                        * return address */
+                       LONG_S          "$gp, " VAL(PT_R28) "($at)\n"
+                       LONG_S          "$sp, " VAL(PT_R29) "($at)\n"
+                       LONG_S          "$fp, " VAL(PT_R30) "($at)\n"
+                       LONG_S          "$ra, " VAL(PT_R31) "($at)\n"
+
+                       /* Now we can get the $at and v0 registers back and
+                        * store them */
+                       LONG_L          "$8, %[at]\n"
+                       LONG_S          "$8, " VAL(PT_R1) "($at)\n"
+                       LONG_L          "$8, %[v0]\n"
+                       LONG_S          "$8, " VAL(PT_R2) "($at)\n"
+                       LONG_L          "$8, %[v1]\n"
+                       LONG_S          "$8, " VAL(PT_R3) "($at)\n"
+               :
+               :
+                       [at] "m" (at),
+                       [v0] "m" (v0),
+                       [v1] "m" (v1),
+                       [pt_regs] "r" (&my_regs)
+               :       "at", "t0"
+               );
+
+               /* Set the current EPC value to be the current location in this
+                * function */
+               __asm__ __volatile__ (
+                       ".set   noat\n"
+               "1:\n"
+                       PTR_LA          "$at, 1b\n"
+                       LONG_S          "$at, %[cp0_epc]\n"
+               :
+                       [cp0_epc] "=m" (my_regs.cp0_epc)
+               :
+               :       "at"
+               );
+
+               my_regs.cp0_cause = read_c0_cause();
+               my_regs.cp0_status = read_c0_status();
+       }
+
+#ifdef CONFIG_DIAGNOSTICS
+       failure_report((char *) cause_string,
+               have_die_regs ? &die_regs : &my_regs);
+       have_die_regs = false;
+#else
+       pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
+               "zzzz... \n");
+#endif
+
+       return NOTIFY_DONE;
+}
+
+/**
+ * Platform-specific handling of oops
+ * @str:       Pointer to the oops string
+ * @regs:      Pointer to the oops registers
+ * All we do here is to save the registers for subsequent printing through
+ * the panic notifier.
+ */
+void platform_die(const char *str, const struct pt_regs *regs)
+{
+       /* If we already have saved registers, don't overwrite them as they
+        * they apply to the initial fault */
+
+       if (!have_die_regs) {
+               have_die_regs = true;
+               die_regs = *regs;
+       }
+}
+
+/* Information about the RF MAC address, if one was supplied on the
+ * command line. */
+static bool have_rfmac;
+static u8 rfmac[ETH_ALEN];
+
+static int rfmac_param(char *p)
+{
+       u8      *q;
+       bool    is_high_nibble;
+       int     c;
+
+       /* Skip a leading "0x", if present */
+       if (*p == '0' && *(p+1) == 'x')
+               p += 2;
+
+       q = rfmac;
+       is_high_nibble = true;
+
+       for (c = (unsigned char) *p++;
+               isxdigit(c) && q - rfmac < ETH_ALEN;
+               c = (unsigned char) *p++) {
+               int     nibble;
+
+               nibble = (isdigit(c) ? (c - '0') :
+                       (isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
+
+               if (is_high_nibble)
+                       *q = nibble << 4;
+               else
+                       *q++ |= nibble;
+
+               is_high_nibble = !is_high_nibble;
+       }
+
+       /* If we parsed all the way to the end of the parameter value and
+        * parsed all ETH_ALEN bytes, we have a usable RF MAC address */
+       have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
+
+       return 0;
+}
+
+early_param("rfmac", rfmac_param);
+
+/*
+ * Generate an Ethernet MAC address that has a good chance of being unique.
+ * @addr:      Pointer to six-byte array containing the Ethernet address
+ * Generates an Ethernet MAC address that is highly likely to be unique for
+ * this particular system on a network with other systems of the same type.
+ *
+ * The problem we are solving is that, when random_ether_addr() is used to
+ * generate MAC addresses at startup, there isn't much entropy for the random
+ * number generator to use and the addresses it produces are fairly likely to
+ * be the same as those of other identical systems on the same local network.
+ * This is true even for relatively small numbers of systems (for the reason
+ * why, see the Wikipedia entry for "Birthday problem" at:
+ *     http://en.wikipedia.org/wiki/Birthday_problem
+ *
+ * The good news is that we already have a MAC address known to be unique, the
+ * RF MAC address. The bad news is that this address is already in use on the
+ * RF interface. Worse, the obvious trick, taking the RF MAC address and
+ * turning on the locally managed bit, has already been used for other devices.
+ * Still, this does give us something to work with.
+ *
+ * The approach we take is:
+ * 1.  If we can't get the RF MAC Address, just call random_ether_addr.
+ * 2.  Use the 24-bit NIC-specific bits of the RF MAC address as the last 24
+ *     bits of the new address. This is very likely to be unique, except for
+ *     the current box.
+ * 3.  To avoid using addresses already on the current box, we set the top
+ *     six bits of the address with a value different from any currently
+ *     registered Scientific Atlanta organizationally unique identifyer
+ *     (OUI). This avoids duplication with any addresses on the system that
+ *     were generated from valid Scientific Atlanta-registered address by
+ *     simply flipping the locally managed bit.
+ * 4.  We aren't generating a multicast address, so we leave the multicast
+ *     bit off. Since we aren't using a registered address, we have to set
+ *     the locally managed bit.
+ * 5.  We then randomly generate the remaining 16-bits. This does two
+ *     things:
+ *     a.      It allows us to call this function for more than one device
+ *             in this system
+ *     b.      It ensures that things will probably still work even if
+ *             some device on the device network has a locally managed
+ *             address that matches the top six bits from step 2.
+ */
+void platform_random_ether_addr(u8 addr[ETH_ALEN])
+{
+       const int num_random_bytes = 2;
+       const unsigned char non_sciatl_oui_bits = 0xc0u;
+       const unsigned char mac_addr_locally_managed = (1 << 1);
+
+       if (!have_rfmac) {
+               pr_warning("rfmac not available on command line; "
+                       "generating random MAC address\n");
+               random_ether_addr(addr);
+       }
+
+       else {
+               int     i;
+
+               /* Set the first byte to something that won't match a Scientific
+                * Atlanta OUI, is locally managed, and isn't a multicast
+                * address */
+               addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
+
+               /* Get some bytes of random address information */
+               get_random_bytes(&addr[1], num_random_bytes);
+
+               /* Copy over the NIC-specific bits of the RF MAC address */
+               for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
+                       addr[i] = rfmac[i];
+       }
+}
diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c
new file mode 100644 (file)
index 0000000..494c652
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/pm.h>
+
+#include <linux/io.h>
+#include <asm/reboot.h>                        /* Not included by linux/reboot.h */
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+#include <asm/mach-powertv/kbldr.h>
+#endif
+
+#include <asm/mach-powertv/asic_regs.h>
+#include "reset.h"
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+
+static void mips_machine_restart(char *command)
+{
+#ifdef CONFIG_BOOTLOADER_DRIVER
+       /*
+        * Call the bootloader's reset function to ensure
+        * that persistent data is flushed before hard reset
+        */
+       kbldr_SetCauseAndReset();
+#else
+       writel(0x1, asic_reg_addr(watchdog));
+#endif
+}
+
+static void mips_machine_halt(void)
+{
+#ifdef CONFIG_BOOTLOADER_DRIVER
+       /*
+        * Call the bootloader's reset function to ensure
+        * that persistent data is flushed before hard reset
+        */
+       kbldr_SetCauseAndReset();
+#else
+       writel(0x1, asic_reg_addr(watchdog));
+#endif
+}
+
+void mips_reboot_setup(void)
+{
+       _machine_restart = mips_machine_restart;
+       _machine_halt = mips_machine_halt;
+       pm_power_off = mips_machine_halt;
+}
diff --git a/arch/mips/powertv/reset.h b/arch/mips/powertv/reset.h
new file mode 100644 (file)
index 0000000..888fd09
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Definitions from powertv reset.c file
+ *
+ * Copyright (C) 2009  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_POWERTV_RESET_H
+#define _POWERTV_POWERTV_RESET_H
+extern void mips_reboot_setup(void);
+#endif
similarity index 60%
rename from arch/mips/mipssim/sim_cmdline.c
rename to arch/mips/powertv/time.c
index 74240e1..1e0a5ef 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * Setting up the clock on the MIPS boards.
  */
+
 #include <linux/init.h>
-#include <linux/string.h>
-#include <asm/bootinfo.h>
+#include <asm/mach-powertv/interrupts.h>
+#include <asm/time.h>
 
-extern char arcs_cmdline[];
+#include "powertv-clock.h"
 
-char * __init prom_getcmdline(void)
+unsigned int __cpuinit get_c0_compare_int(void)
 {
-       return arcs_cmdline;
+       return irq_mips_timer;
 }
 
-void  __init prom_init_cmdline(void)
+void __init plat_time_init(void)
 {
-       /* XXX: Get boot line from environment? */
+       powertv_clocksource_init();
+       r4k_clockevent_init();
 }
index ad5bd10..d7c26d0 100644 (file)
@@ -69,7 +69,7 @@ static inline unsigned long tag2ul(char *arg, const char *tag)
 
 void __init prom_setup_cmdline(void)
 {
-       static char cmd_line[CL_SIZE] __initdata;
+       static char cmd_line[COMMAND_LINE_SIZE] __initdata;
        char *cp, *board;
        int prom_argc;
        char **prom_argv, **prom_envp;
@@ -115,7 +115,7 @@ void __init prom_setup_cmdline(void)
                strcpy(cp, arcs_cmdline);
                cp += strlen(arcs_cmdline);
        }
-       cmd_line[CL_SIZE-1] = '\0';
+       cmd_line[COMMAND_LINE_SIZE - 1] = '\0';
 
        strcpy(arcs_cmdline, cmd_line);
 }
index 1617241..da44ccb 100644 (file)
@@ -50,9 +50,9 @@
 
 static char __init *decode_eisa_sig(unsigned long addr)
 {
-        static char sig_str[EISA_SIG_LEN];
+       static char sig_str[EISA_SIG_LEN] __initdata;
        u8 sig[4];
-        u16 rev;
+       u16 rev;
        int i;
 
        for (i = 0; i < 4; i++) {
index 0ecd5fe..383f11d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
+#include <linux/ftrace.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/sgi/hpc3.h>
@@ -150,7 +151,7 @@ static void indy_local1_irqdispatch(void)
 
 extern void ip22_be_interrupt(int irq);
 
-static void indy_buserror_irq(void)
+static void __irq_entry indy_buserror_irq(void)
 {
        int irq = SGI_BUSERR_IRQ;
 
index b9a9313..5deeb68 100644 (file)
@@ -67,7 +67,7 @@ void __init plat_mem_setup(void)
        cserial = ArcGetEnvironmentVariable("ConsoleOut");
 
        if ((ctype && *ctype == 'd') || (cserial && *cserial == 's')) {
-               static char options[8];
+               static char options[8] __initdata;
                char *baud = ArcGetEnvironmentVariable("dbaud");
                if (baud)
                        strcpy(options, baud);
index c8f7d23..603fc91 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/time.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/mipsregs.h>
@@ -115,7 +116,7 @@ __init void plat_time_init(void)
 }
 
 /* Generic SGI handler for (spurious) 8254 interrupts */
-void indy_8254timer_irq(void)
+void __irq_entry indy_8254timer_irq(void)
 {
        int irq = SGI_8254_0_IRQ;
        ULONG cnt;
index c5a5d4a..3abd146 100644 (file)
@@ -90,7 +90,7 @@ void __init plat_mem_setup(void)
        {
                char* con = ArcGetEnvironmentVariable("console");
                if (con && *con == 'd') {
-                       static char options[8];
+                       static char options[8] __initdata;
                        char *baud = ArcGetEnvironmentVariable("dbaud");
                        if (baud)
                                strcpy(options, baud);
index eb5396c..6343011 100644 (file)
@@ -287,7 +287,7 @@ void __init prom_init(void)
         * boot console
         */
        cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-       if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
+       if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, COMMAND_LINE_SIZE) < 0) {
                if (argc >= 0) {
                        /* The loader should have set the command line */
                        /* too early for panic to do any good */
@@ -318,7 +318,7 @@ void __init prom_init(void)
 #endif /* CONFIG_BLK_DEV_INITRD */
 
        /* Not sure this is needed, but it's the safe way. */
-       arcs_cmdline[CL_SIZE-1] = 0;
+       arcs_cmdline[COMMAND_LINE_SIZE-1] = 0;
 
        prom_meminit();
 
index 7dd76fb..e698089 100644 (file)
@@ -188,7 +188,7 @@ static void end_a20r_irq(unsigned int irq)
 }
 
 static struct irq_chip a20r_irq_type = {
-       .typename       = "A20R",
+       .name           = "A20R",
        .ack            = mask_a20r_irq,
        .mask           = mask_a20r_irq,
        .mask_ack       = mask_a20r_irq,
index 74e6c67..51e62bb 100644 (file)
@@ -214,7 +214,7 @@ static void end_pcimt_irq(unsigned int irq)
 }
 
 static struct irq_chip pcimt_irq_type = {
-       .typename = "PCIMT",
+       .name = "PCIMT",
        .ack = disable_pcimt_irq,
        .mask = disable_pcimt_irq,
        .mask_ack = disable_pcimt_irq,
index 071a957..f4699d3 100644 (file)
@@ -176,7 +176,7 @@ void end_pcit_irq(unsigned int irq)
 }
 
 static struct irq_chip pcit_irq_type = {
-       .typename = "PCIT",
+       .name = "PCIT",
        .ack = disable_pcit_irq,
        .mask = disable_pcit_irq,
        .mask_ack = disable_pcit_irq,
index 5e68781..46f0069 100644 (file)
@@ -449,7 +449,7 @@ void end_rm200_irq(unsigned int irq)
 }
 
 static struct irq_chip rm200_irq_type = {
-       .typename = "RM200",
+       .name = "RM200",
        .ack = disable_rm200_irq,
        .mask = disable_rm200_irq,
        .mask_ack = disable_rm200_irq,
index a49272c..d16b462 100644 (file)
@@ -60,7 +60,7 @@ static void __init sni_console_setup(void)
        char *cdev;
        char *baud;
        int port;
-       static char options[8];
+       static char options[8] __initdata;
 
        cdev = prom_getenv("console_dev");
        if (strncmp(cdev, "tty", 3) == 0) {
index d66802e..06e801c 100644 (file)
@@ -160,7 +160,7 @@ static void __init prom_init_cmdline(void)
        int argc;
        int *argv32;
        int i;                  /* Always ignore the "-c" at argv[0] */
-       static char builtin[CL_SIZE] __initdata;
+       static char builtin[COMMAND_LINE_SIZE] __initdata;
 
        if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) {
                /*
@@ -315,7 +315,7 @@ static inline void txx9_cache_fixup(void)
 
 static void __init preprocess_cmdline(void)
 {
-       static char cmdline[CL_SIZE] __initdata;
+       static char cmdline[COMMAND_LINE_SIZE] __initdata;
        char *s;
 
        strcpy(cmdline, arcs_cmdline);
diff --git a/arch/mn10300/include/asm/asm-offsets.h b/arch/mn10300/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/parisc/include/asm/asm-offsets.h b/arch/parisc/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/powerpc/include/asm/asm-offsets.h b/arch/powerpc/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index bcc69e1..45c0cb9 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/pci.h>
 #include <linux/of.h>
 #include <asm/prom.h>
index 9290a7a..fb4eb0d 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/seq_file.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 #include <asm/machdep.h>
 #include <asm/cputable.h>
index b93f877..b9d5d67 100644 (file)
@@ -13,10 +13,8 @@ SPU_CC               := $(SPU_CROSS)gcc
 SPU_AS         := $(SPU_CROSS)gcc
 SPU_LD         := $(SPU_CROSS)ld
 SPU_OBJCOPY    := $(SPU_CROSS)objcopy
-SPU_CFLAGS     := -O2 -Wall -I$(srctree)/include \
-                  -I$(objtree)/include2 -D__KERNEL__
-SPU_AFLAGS     := -c -D__ASSEMBLY__ -I$(srctree)/include \
-                  -I$(objtree)/include2 -D__KERNEL__
+SPU_CFLAGS     := -O2 -Wall -I$(srctree)/include -D__KERNEL__
+SPU_AFLAGS     := -c -D__ASSEMBLY__ -I$(srctree)/include -D__KERNEL__
 SPU_LDFLAGS    := -N -Ttext=0x0
 
 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
index 52f3df3..8f41685 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/adb.h>
 #include <linux/module.h>
 #include <linux/delay.h>
index cf66091..9dd789a 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
 #include <asm/page.h>
diff --git a/arch/s390/include/asm/asm-offsets.h b/arch/s390/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/score/include/asm/asm-offsets.h b/arch/score/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index caaba24..1d545d0 100644 (file)
@@ -14,10 +14,12 @@ extern void flush_cache_sigtramp(unsigned long addr);
 extern void flush_icache_all(void);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void flush_dcache_range(unsigned long start, unsigned long end);
+extern void flush_dcache_page(struct page *page);
+
+#define PG_dcache_dirty         PG_arch_1
 
 #define flush_cache_dup_mm(mm)                 do {} while (0)
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)                        do {} while (0)
 #define flush_dcache_mmap_lock(mapping)                do {} while (0)
 #define flush_dcache_mmap_unlock(mapping)      do {} while (0)
 #define flush_cache_vmap(start, end)           do {} while (0)
index 6726ec1..529e494 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_SCORE_DELAY_H
 #define _ASM_SCORE_DELAY_H
 
+#include <asm-generic/param.h>
+
 static inline void __delay(unsigned long loops)
 {
        /* 3 cycles per loop. */
index d92a5a2..1e9ade8 100644 (file)
@@ -74,7 +74,7 @@ extern unsigned long max_pfn;
 #define page_to_bus(page)      (page_to_phys(page))
 #define phys_to_page(paddr)    (pfn_to_page(phys_to_pfn(paddr)))
 
-#define pfn_valid(pfn)         ((pfn) >= min_low_pfn && (pfn) < max_mapnr)
+#define pfn_valid(pfn)         (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn))
 
 #define ARCH_PFN_OFFSET                (PAGE_OFFSET >> PAGE_SHIFT)
 
index 6a2503c..6f898c0 100644 (file)
@@ -49,6 +49,7 @@ static void __init bootmem_init(void)
 
        min_low_pfn = PFN_UP(MEMORY_START);
        max_low_pfn = PFN_UP(MEMORY_START + MEMORY_SIZE);
+       max_mapnr = max_low_pfn - min_low_pfn;
 
        /* Initialize the boot-time allocator with low memory only. */
        bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
index dbac9d9..b25e957 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/fs.h>
 
 #include <asm/mmu_context.h>
 
@@ -51,6 +52,27 @@ static void flush_data_cache_page(unsigned long addr)
        }
 }
 
+void flush_dcache_page(struct page *page)
+{
+       struct address_space *mapping = page_mapping(page);
+       unsigned long addr;
+
+       if (PageHighMem(page))
+               return;
+       if (mapping && !mapping_mapped(mapping)) {
+               set_bit(PG_dcache_dirty, &(page)->flags);
+               return;
+       }
+
+       /*
+        * We could delay the flush for the !page_mapping case too.  But that
+        * case is for exec env/arg pages and those are %99 certainly going to
+        * get faulted into the tlb (and thus flushed) anyways.
+        */
+       addr = (unsigned long) page_address(page);
+       flush_data_cache_page(addr);
+}
+
 /* called by update_mmu_cache. */
 void __update_cache(struct vm_area_struct *vma, unsigned long address,
                pte_t pte)
@@ -63,11 +85,11 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
        if (unlikely(!pfn_valid(pfn)))
                return;
        page = pfn_to_page(pfn);
-       if (page_mapping(page) && test_bit(PG_arch_1, &page->flags)) {
+       if (page_mapping(page) && test_bit(PG_dcache_dirty, &(page)->flags)) {
                addr = (unsigned long) page_address(page);
                if (exec)
                        flush_data_cache_page(addr);
-               clear_bit(PG_arch_1, &page->flags);
+               clear_bit(PG_dcache_dirty, &(page)->flags);
        }
 }
 
index 4e3dcd0..8c15b2c 100644 (file)
@@ -83,7 +83,6 @@ void __init mem_init(void)
        unsigned long codesize, reservedpages, datasize, initsize;
        unsigned long tmp, ram = 0;
 
-       max_mapnr = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
        totalram_pages += free_all_bootmem();
        totalram_pages -= setup_zero_page();    /* Setup zeroed pages. */
@@ -101,10 +100,6 @@ void __init mem_init(void)
        datasize = (unsigned long) &_edata - (unsigned long) &_etext;
        initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
-       kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
-       kclist_add(&kcore_vmalloc, (void *) VMALLOC_START,
-                       VMALLOC_END - VMALLOC_START);
-
        printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
                        "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
                        (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
index ac17c5a..db91925 100644 (file)
@@ -205,10 +205,7 @@ libs-$(CONFIG_SUPERH64)            := arch/sh/lib64/ $(libs-y)
 
 BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec uImage.bin \
               zImage vmlinux.srec romImage
-PHONY += maketools $(BOOT_TARGETS) FORCE
-
-maketools:  include/linux/version.h FORCE
-       $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
+PHONY += $(BOOT_TARGETS)
 
 all: $(KBUILD_IMAGE)
 
@@ -217,7 +214,8 @@ $(BOOT_TARGETS): vmlinux
 
 compressed: zImage
 
-archprepare: maketools
+archprepare:
+       $(Q)$(MAKE) $(build)=arch/sh/tools include/generated/machtypes.h
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
@@ -234,5 +232,3 @@ define archhelp
        @echo '  uImage.bz2                - Kernel-only image for U-Boot (bzip2)'
        @echo '  uImage.lzma               - Kernel-only image for U-Boot (lzma)'
 endef
-
-CLEAN_FILES += include/asm-sh/machtypes.h
index 052b354..7898f14 100644 (file)
@@ -15,7 +15,7 @@
 #include <mach/lboxre2.h>
 #include <mach/r2d.h>
 #include "pci-sh4.h"
-#include <asm/machtypes.h>
+#include <generated/machtypes.h>
 
 #define PCIMCR_MRSET_OFF       0xBFFFFFFF
 #define PCIMCR_RFSH_OFF                0xFFFFFFFB
diff --git a/arch/sh/include/asm/.gitignore b/arch/sh/include/asm/.gitignore
deleted file mode 100644 (file)
index 378db77..0000000
+++ /dev/null
@@ -1 +0,0 @@
-machtypes.h
diff --git a/arch/sh/include/asm/asm-offsets.h b/arch/sh/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 84dd377..9c30955 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/time.h>
-#include <asm/machtypes.h>
+#include <generated/machtypes.h>
 
 struct sh_machine_vector {
        void (*mv_setup)(char **cmdline_p);
index 567516b..558a56b 100644 (file)
@@ -10,7 +10,7 @@
 # Shamelessly cloned from ARM.
 #
 
-include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
+include/generated/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
        @echo '  Generating $@'
-       $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
+       $(Q)mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index 65161e3..f5ff7c5 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/awk
 #
-# Awk script to generate include/asm-sh/machtypes.h
+# Awk script to generate include/generated/machtypes.h
 # Heavily based on arch/arm/tools/gen-mach-types
 #
 BEGIN  { nr = 0 }
diff --git a/arch/sparc/include/asm/asm-offsets.h b/arch/sparc/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index 3b9cfb3..38f37b3 100644 (file)
@@ -19,7 +19,7 @@
 #define O_NOATIME      0x200000
 #define O_CLOEXEC      0x400000
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
index fc633db..fab8121 100644 (file)
@@ -149,6 +149,6 @@ $(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
 
 $(SHARED_HEADERS)/kern_constants.h:
        $(Q)mkdir -p $(dir $@)
-       $(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
+       $(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
 
 export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
diff --git a/arch/um/include/asm/asm-offsets.h b/arch/um/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index b31cc54..93e689f 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #include <asm/segment.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page_types.h>
index 2723d9b..2b15aa4 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include "boot.h"
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
+#include <generated/utsrelease.h>
+#include <generated/compile.h>
 
 const char kernel_version[] =
        UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") "
diff --git a/arch/x86/include/asm/asm-offsets.h b/arch/x86/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index a9df944..f125e5c 100644 (file)
@@ -1136,7 +1136,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        if (!alloc_cpumask_var(&oldmask, GFP_KERNEL))
                return -ENOMEM;
 
-       cpumask_copy(oldmask, tsk_cpumask(current));
+       cpumask_copy(oldmask, tsk_cpus_allowed(current));
        set_cpus_allowed_ptr(current, cpumask_of(pol->cpu));
 
        if (smp_processor_id() != pol->cpu) {
index 2779321..017d937 100644 (file)
@@ -509,14 +509,14 @@ static int genregs_get(struct task_struct *target,
 {
        if (kbuf) {
                unsigned long *k = kbuf;
-               while (count > 0) {
+               while (count >= sizeof(*k)) {
                        *k++ = getreg(target, pos);
                        count -= sizeof(*k);
                        pos += sizeof(*k);
                }
        } else {
                unsigned long __user *u = ubuf;
-               while (count > 0) {
+               while (count >= sizeof(*u)) {
                        if (__put_user(getreg(target, pos), u++))
                                return -EFAULT;
                        count -= sizeof(*u);
@@ -535,14 +535,14 @@ static int genregs_set(struct task_struct *target,
        int ret = 0;
        if (kbuf) {
                const unsigned long *k = kbuf;
-               while (count > 0 && !ret) {
+               while (count >= sizeof(*k) && !ret) {
                        ret = putreg(target, pos, *k++);
                        count -= sizeof(*k);
                        pos += sizeof(*k);
                }
        } else {
                const unsigned long  __user *u = ubuf;
-               while (count > 0 && !ret) {
+               while (count >= sizeof(*u) && !ret) {
                        unsigned long word;
                        ret = __get_user(word, u++);
                        if (ret)
@@ -1458,14 +1458,14 @@ static int genregs32_get(struct task_struct *target,
 {
        if (kbuf) {
                compat_ulong_t *k = kbuf;
-               while (count > 0) {
+               while (count >= sizeof(*k)) {
                        getreg32(target, pos, k++);
                        count -= sizeof(*k);
                        pos += sizeof(*k);
                }
        } else {
                compat_ulong_t __user *u = ubuf;
-               while (count > 0) {
+               while (count >= sizeof(*u)) {
                        compat_ulong_t word;
                        getreg32(target, pos, &word);
                        if (__put_user(word, u++))
@@ -1486,14 +1486,14 @@ static int genregs32_set(struct task_struct *target,
        int ret = 0;
        if (kbuf) {
                const compat_ulong_t *k = kbuf;
-               while (count > 0 && !ret) {
+               while (count >= sizeof(*k) && !ret) {
                        ret = putreg32(target, pos, *k++);
                        count -= sizeof(*k);
                        pos += sizeof(*k);
                }
        } else {
                const compat_ulong_t __user *u = ubuf;
-               while (count > 0 && !ret) {
+               while (count >= sizeof(*u) && !ret) {
                        compat_ulong_t word;
                        ret = __get_user(word, u++);
                        if (ret)
diff --git a/arch/xtensa/include/asm/asm-offsets.h b/arch/xtensa/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..d370ee3
--- /dev/null
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
index d672cfe..cb423f5 100644 (file)
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/autoconf.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
index 27ae750..bf31592 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __HID_LG_H
 #define __HID_LG_H
 
-#include <linux/autoconf.h>
-
 #ifdef CONFIG_LOGITECH_FF
 int lgff_init(struct hid_device *hdev);
 #else
index 95ccbe3..46c3c56 100644 (file)
@@ -228,6 +228,18 @@ config SENSORS_K8TEMP
          This driver can also be built as a module.  If so, the module
          will be called k8temp.
 
+config SENSORS_K10TEMP
+       tristate "AMD Phenom/Sempron/Turion/Opteron temperature sensor"
+       depends on X86 && PCI
+       help
+         If you say yes here you get support for the temperature
+         sensor(s) inside your CPU. Supported are later revisions of
+         the AMD Family 10h and all revisions of the AMD Family 11h
+         microarchitectures.
+
+         This driver can also be built as a module.  If so, the module
+         will be called k10temp.
+
 config SENSORS_AMS
        tristate "Apple Motion Sensor driver"
        depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
@@ -810,6 +822,14 @@ config SENSORS_TMP421
          This driver can also be built as a module.  If so, the module
          will be called tmp421.
 
+config SENSORS_VIA_CPUTEMP
+       tristate "VIA CPU temperature sensor"
+       depends on X86
+       help
+         If you say yes here you get support for the temperature
+         sensor inside your CPU. Supported are all known variants of
+         the VIA C7 and Nano.
+
 config SENSORS_VIA686A
        tristate "VIA686A"
        depends on PCI
@@ -998,6 +1018,23 @@ config SENSORS_LIS3_SPI
          will be called lis3lv02d and a specific module for the SPI transport
          is called lis3lv02d_spi.
 
+config SENSORS_LIS3_I2C
+       tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
+       depends on I2C && INPUT
+       select INPUT_POLLDEV
+       default n
+       help
+         This driver provides support for the LIS3LV02Dx accelerometer connected
+         via I2C. The accelerometer data is readable via
+         /sys/devices/platform/lis3lv02d.
+
+         This driver also provides an absolute input class device, allowing
+         the device to act as a pinball machine-esque joystick.
+
+         This driver can also be built as modules.  If so, the core module
+         will be called lis3lv02d and a specific module for the I2C transport
+         is called lis3lv02d_i2c.
+
 config SENSORS_APPLESMC
        tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
        depends on INPUT && X86
index 33c2ee1..450c8e8 100644 (file)
@@ -53,8 +53,10 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)   += ibmpex.o
 obj-$(CONFIG_SENSORS_IT87)     += it87.o
 obj-$(CONFIG_SENSORS_K8TEMP)   += k8temp.o
+obj-$(CONFIG_SENSORS_K10TEMP)  += k10temp.o
 obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
 obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o
+obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o
 obj-$(CONFIG_SENSORS_LM63)     += lm63.o
 obj-$(CONFIG_SENSORS_LM70)     += lm70.o
 obj-$(CONFIG_SENSORS_LM73)     += lm73.o
@@ -87,6 +89,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_THMC50)   += thmc50.o
 obj-$(CONFIG_SENSORS_TMP401)   += tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)   += tmp421.o
+obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)  += via686a.o
 obj-$(CONFIG_SENSORS_VT1211)   += vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)   += vt8231.o
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
new file mode 100644 (file)
index 0000000..d8a26d1
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * k10temp.c - AMD Family 10h/11h processor hardware monitoring
+ *
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This driver 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 driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <asm/processor.h>
+
+MODULE_DESCRIPTION("AMD Family 10h/11h CPU core temperature monitor");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL");
+
+static bool force;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
+
+#define REG_HARDWARE_THERMAL_CONTROL   0x64
+#define  HTC_ENABLE                    0x00000001
+
+#define REG_REPORTED_TEMPERATURE       0xa4
+
+#define REG_NORTHBRIDGE_CAPABILITIES   0xe8
+#define  NB_CAP_HTC                    0x00000400
+
+static ssize_t show_temp(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       u32 regval;
+
+       pci_read_config_dword(to_pci_dev(dev),
+                             REG_REPORTED_TEMPERATURE, &regval);
+       return sprintf(buf, "%u\n", (regval >> 21) * 125);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", 70 * 1000);
+}
+
+static ssize_t show_temp_crit(struct device *dev,
+                             struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       int show_hyst = attr->index;
+       u32 regval;
+       int value;
+
+       pci_read_config_dword(to_pci_dev(dev),
+                             REG_HARDWARE_THERMAL_CONTROL, &regval);
+       value = ((regval >> 16) & 0x7f) * 500 + 52000;
+       if (show_hyst)
+               value -= ((regval >> 24) & 0xf) * 500;
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_name(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "k10temp\n");
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static bool __devinit has_erratum_319(void)
+{
+       /*
+        * Erratum 319: The thermal sensor of older Family 10h processors
+        *              (B steppings) may be unreliable.
+        */
+       return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
+}
+
+static int __devinit k10temp_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *id)
+{
+       struct device *hwmon_dev;
+       u32 reg_caps, reg_htc;
+       int err;
+
+       if (has_erratum_319() && !force) {
+               dev_err(&pdev->dev,
+                       "unreliable CPU thermal sensor; monitoring disabled\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       err = device_create_file(&pdev->dev, &dev_attr_temp1_input);
+       if (err)
+               goto exit;
+       err = device_create_file(&pdev->dev, &dev_attr_temp1_max);
+       if (err)
+               goto exit_remove;
+
+       pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, &reg_caps);
+       pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, &reg_htc);
+       if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) {
+               err = device_create_file(&pdev->dev,
+                               &sensor_dev_attr_temp1_crit.dev_attr);
+               if (err)
+                       goto exit_remove;
+               err = device_create_file(&pdev->dev,
+                               &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+               if (err)
+                       goto exit_remove;
+       }
+
+       err = device_create_file(&pdev->dev, &dev_attr_name);
+       if (err)
+               goto exit_remove;
+
+       hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(hwmon_dev)) {
+               err = PTR_ERR(hwmon_dev);
+               goto exit_remove;
+       }
+       dev_set_drvdata(&pdev->dev, hwmon_dev);
+
+       if (has_erratum_319() && force)
+               dev_warn(&pdev->dev,
+                        "unreliable CPU thermal sensor; check erratum 319\n");
+       return 0;
+
+exit_remove:
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       device_remove_file(&pdev->dev, &dev_attr_temp1_input);
+       device_remove_file(&pdev->dev, &dev_attr_temp1_max);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_crit.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+exit:
+       return err;
+}
+
+static void __devexit k10temp_remove(struct pci_dev *pdev)
+{
+       hwmon_device_unregister(dev_get_drvdata(&pdev->dev));
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       device_remove_file(&pdev->dev, &dev_attr_temp1_input);
+       device_remove_file(&pdev->dev, &dev_attr_temp1_max);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_crit.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+       dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static struct pci_device_id k10temp_id_table[] = {
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
+       {}
+};
+MODULE_DEVICE_TABLE(pci, k10temp_id_table);
+
+static struct pci_driver k10temp_driver = {
+       .name = "k10temp",
+       .id_table = k10temp_id_table,
+       .probe = k10temp_probe,
+       .remove = __devexit_p(k10temp_remove),
+};
+
+static int __init k10temp_init(void)
+{
+       return pci_register_driver(&k10temp_driver);
+}
+
+static void __exit k10temp_exit(void)
+{
+       pci_unregister_driver(&k10temp_driver);
+}
+
+module_init(k10temp_init)
+module_exit(k10temp_exit)
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
new file mode 100644 (file)
index 0000000..dc1f540
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * drivers/hwmon/lis3lv02d_i2c.c
+ *
+ * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
+ * Driver is based on corresponding SPI driver written by Daniel Mack
+ * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "lis3lv02d.h"
+
+#define DRV_NAME       "lis3lv02d_i2c"
+
+static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       *v = i2c_smbus_read_byte_data(c, reg);
+       return 0;
+}
+
+static int lis3_i2c_init(struct lis3lv02d *lis3)
+{
+       u8 reg;
+       int ret;
+
+       /* power up the device */
+       ret = lis3->read(lis3, CTRL_REG1, &reg);
+       if (ret < 0)
+               return ret;
+
+       reg |= CTRL1_PD0;
+       return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+/* Default axis mapping but it can be overwritten by platform data */
+static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
+                                                    LIS3_DEV_Y,
+                                                    LIS3_DEV_Z };
+
+static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+       if (pdata) {
+               if (pdata->axis_x)
+                       lis3lv02d_axis_map.x = pdata->axis_x;
+
+               if (pdata->axis_y)
+                       lis3lv02d_axis_map.y = pdata->axis_y;
+
+               if (pdata->axis_z)
+                       lis3lv02d_axis_map.z = pdata->axis_z;
+
+               if (pdata->setup_resources)
+                       ret = pdata->setup_resources();
+
+               if (ret)
+                       goto fail;
+       }
+
+       lis3_dev.pdata    = pdata;
+       lis3_dev.bus_priv = client;
+       lis3_dev.init     = lis3_i2c_init;
+       lis3_dev.read     = lis3_i2c_read;
+       lis3_dev.write    = lis3_i2c_write;
+       lis3_dev.irq      = client->irq;
+       lis3_dev.ac       = lis3lv02d_axis_map;
+
+       i2c_set_clientdata(client, &lis3_dev);
+       ret = lis3lv02d_init_device(&lis3_dev);
+fail:
+       return ret;
+}
+
+static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+{
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+       struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+       if (pdata && pdata->release_resources)
+               pdata->release_resources();
+
+       lis3lv02d_joystick_disable();
+       lis3lv02d_poweroff(lis3);
+
+       return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+#ifdef CONFIG_PM
+static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       if (!lis3->pdata->wakeup_flags)
+               lis3lv02d_poweroff(lis3);
+       return 0;
+}
+
+static int lis3lv02d_i2c_resume(struct i2c_client *client)
+{
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       if (!lis3->pdata->wakeup_flags)
+               lis3lv02d_poweron(lis3);
+       return 0;
+}
+
+static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
+{
+       lis3lv02d_i2c_suspend(client, PMSG_SUSPEND);
+}
+#else
+#define lis3lv02d_i2c_suspend  NULL
+#define lis3lv02d_i2c_resume   NULL
+#define lis3lv02d_i2c_shutdown NULL
+#endif
+
+static const struct i2c_device_id lis3lv02d_id[] = {
+       {"lis3lv02d", 0 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
+
+static struct i2c_driver lis3lv02d_i2c_driver = {
+       .driver  = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .suspend = lis3lv02d_i2c_suspend,
+       .shutdown = lis3lv02d_i2c_shutdown,
+       .resume = lis3lv02d_i2c_resume,
+       .probe  = lis3lv02d_i2c_probe,
+       .remove = __devexit_p(lis3lv02d_i2c_remove),
+       .id_table = lis3lv02d_id,
+};
+
+static int __init lis3lv02d_init(void)
+{
+       return i2c_add_driver(&lis3lv02d_i2c_driver);
+}
+
+static void __exit lis3lv02d_exit(void)
+{
+       i2c_del_driver(&lis3lv02d_i2c_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("lis3lv02d I2C interface");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init);
+module_exit(lis3lv02d_exit);
index ebe38b6..864a371 100644 (file)
@@ -305,7 +305,7 @@ static inline int sht15_calc_temp(struct sht15_data *data)
        int d1 = 0;
        int i;
 
-       for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++)
+       for (i = 1; i < ARRAY_SIZE(temppoints); i++)
                /* Find pointer to interpolate */
                if (data->supply_uV > temppoints[i - 1].vdd) {
                        d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd)
@@ -332,12 +332,12 @@ static inline int sht15_calc_humid(struct sht15_data *data)
 
        const int c1 = -4;
        const int c2 = 40500; /* x 10 ^ -6 */
-       const int c3 = 2800; /* x10 ^ -9 */
+       const int c3 = -2800; /* x10 ^ -9 */
 
        RHlinear = c1*1000
                + c2 * data->val_humid/1000
                + (data->val_humid * data->val_humid * c3)/1000000;
-       return (temp - 25000) * (10000 + 800 * data->val_humid)
+       return (temp - 25000) * (10000 + 80 * data->val_humid)
                / 1000000 + RHlinear;
 }
 
index 8ad50fd..9ca9781 100644 (file)
@@ -136,11 +136,11 @@ struct smsc47m1_data {
 
 struct smsc47m1_sio_data {
        enum chips type;
+       u8 activate;            /* Remember initial device state */
 };
 
 
-static int smsc47m1_probe(struct platform_device *pdev);
-static int __devexit smsc47m1_remove(struct platform_device *pdev);
+static int __exit smsc47m1_remove(struct platform_device *pdev);
 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
                int init);
 
@@ -160,8 +160,7 @@ static struct platform_driver smsc47m1_driver = {
                .owner  = THIS_MODULE,
                .name   = DRVNAME,
        },
-       .probe          = smsc47m1_probe,
-       .remove         = __devexit_p(smsc47m1_remove),
+       .remove         = __exit_p(smsc47m1_remove),
 };
 
 static ssize_t get_fan(struct device *dev, struct device_attribute
@@ -470,24 +469,126 @@ static int __init smsc47m1_find(unsigned short *addr,
        superio_select();
        *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
              |  superio_inb(SUPERIO_REG_BASE + 1);
-       val = superio_inb(SUPERIO_REG_ACT);
-       if (*addr == 0 || (val & 0x01) == 0) {
-               pr_info(DRVNAME ": Device is disabled, will not use\n");
+       if (*addr == 0) {
+               pr_info(DRVNAME ": Device address not set, will not use\n");
                superio_exit();
                return -ENODEV;
        }
 
+       /* Enable only if address is set (needed at least on the
+        * Compaq Presario S4000NX) */
+       sio_data->activate = superio_inb(SUPERIO_REG_ACT);
+       if ((sio_data->activate & 0x01) == 0) {
+               pr_info(DRVNAME ": Enabling device\n");
+               superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
+       }
+
        superio_exit();
        return 0;
 }
 
-static int __devinit smsc47m1_probe(struct platform_device *pdev)
+/* Restore device to its initial state */
+static void __init smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
+{
+       if ((sio_data->activate & 0x01) == 0) {
+               superio_enter();
+               superio_select();
+
+               pr_info(DRVNAME ": Disabling device\n");
+               superio_outb(SUPERIO_REG_ACT, sio_data->activate);
+
+               superio_exit();
+       }
+}
+
+#define CHECK          1
+#define REQUEST                2
+#define RELEASE                3
+
+/*
+ * This function can be used to:
+ *  - test for resource conflicts with ACPI
+ *  - request the resources
+ *  - release the resources
+ * We only allocate the I/O ports we really need, to minimize the risk of
+ * conflicts with ACPI or with other drivers.
+ */
+static int smsc47m1_handle_resources(unsigned short address, enum chips type,
+                                    int action, struct device *dev)
+{
+       static const u8 ports_m1[] = {
+               /* register, region length */
+               0x04, 1,
+               0x33, 4,
+               0x56, 7,
+       };
+
+       static const u8 ports_m2[] = {
+               /* register, region length */
+               0x04, 1,
+               0x09, 1,
+               0x2c, 2,
+               0x35, 4,
+               0x56, 7,
+               0x69, 4,
+       };
+
+       int i, ports_size, err;
+       const u8 *ports;
+
+       switch (type) {
+       case smsc47m1:
+       default:
+               ports = ports_m1;
+               ports_size = ARRAY_SIZE(ports_m1);
+               break;
+       case smsc47m2:
+               ports = ports_m2;
+               ports_size = ARRAY_SIZE(ports_m2);
+               break;
+       }
+
+       for (i = 0; i + 1 < ports_size; i += 2) {
+               unsigned short start = address + ports[i];
+               unsigned short len = ports[i + 1];
+
+               switch (action) {
+               case CHECK:
+                       /* Only check for conflicts */
+                       err = acpi_check_region(start, len, DRVNAME);
+                       if (err)
+                               return err;
+                       break;
+               case REQUEST:
+                       /* Request the resources */
+                       if (!request_region(start, len, DRVNAME)) {
+                               dev_err(dev, "Region 0x%hx-0x%hx already in "
+                                       "use!\n", start, start + len);
+
+                               /* Undo all requests */
+                               for (i -= 2; i >= 0; i -= 2)
+                                       release_region(address + ports[i],
+                                                      ports[i + 1]);
+                               return -EBUSY;
+                       }
+                       break;
+               case RELEASE:
+                       /* Release the resources */
+                       release_region(start, len);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int __init smsc47m1_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct smsc47m1_sio_data *sio_data = dev->platform_data;
        struct smsc47m1_data *data;
        struct resource *res;
-       int err = 0;
+       int err;
        int fan1, fan2, fan3, pwm1, pwm2, pwm3;
 
        static const char *names[] = {
@@ -496,12 +597,10 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
        };
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) {
-               dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-                       (unsigned long)res->start,
-                       (unsigned long)res->end);
-               return -EBUSY;
-       }
+       err = smsc47m1_handle_resources(res->start, sio_data->type,
+                                       REQUEST, dev);
+       if (err < 0)
+               return err;
 
        if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
                err = -ENOMEM;
@@ -637,11 +736,11 @@ error_free:
        platform_set_drvdata(pdev, NULL);
        kfree(data);
 error_release:
-       release_region(res->start, SMSC_EXTENT);
+       smsc47m1_handle_resources(res->start, sio_data->type, RELEASE, dev);
        return err;
 }
 
-static int __devexit smsc47m1_remove(struct platform_device *pdev)
+static int __exit smsc47m1_remove(struct platform_device *pdev)
 {
        struct smsc47m1_data *data = platform_get_drvdata(pdev);
        struct resource *res;
@@ -650,7 +749,7 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       release_region(res->start, SMSC_EXTENT);
+       smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev);
        platform_set_drvdata(pdev, NULL);
        kfree(data);
 
@@ -717,7 +816,7 @@ static int __init smsc47m1_device_add(unsigned short address,
        };
        int err;
 
-       err = acpi_check_resource_conflict(&res);
+       err = smsc47m1_handle_resources(address, sio_data->type, CHECK, NULL);
        if (err)
                goto exit;
 
@@ -766,27 +865,29 @@ static int __init sm_smsc47m1_init(void)
        if (smsc47m1_find(&address, &sio_data))
                return -ENODEV;
 
-       err = platform_driver_register(&smsc47m1_driver);
+       /* Sets global pdev as a side effect */
+       err = smsc47m1_device_add(address, &sio_data);
        if (err)
                goto exit;
 
-       /* Sets global pdev as a side effect */
-       err = smsc47m1_device_add(address, &sio_data);
+       err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe);
        if (err)
-               goto exit_driver;
+               goto exit_device;
 
        return 0;
 
-exit_driver:
-       platform_driver_unregister(&smsc47m1_driver);
+exit_device:
+       platform_device_unregister(pdev);
+       smsc47m1_restore(&sio_data);
 exit:
        return err;
 }
 
 static void __exit sm_smsc47m1_exit(void)
 {
-       platform_device_unregister(pdev);
        platform_driver_unregister(&smsc47m1_driver);
+       smsc47m1_restore(pdev->dev.platform_data);
+       platform_device_unregister(pdev);
 }
 
 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
new file mode 100644 (file)
index 0000000..7442cf7
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * via-cputemp.c - Driver for VIA CPU core temperature monitoring
+ * Copyright (C) 2009 VIA Technologies, Inc.
+ *
+ * based on existing coretemp.c, which is
+ *
+ * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+#define DRVNAME        "via_cputemp"
+
+enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW;
+
+/*
+ * Functions declaration
+ */
+
+struct via_cputemp_data {
+       struct device *hwmon_dev;
+       const char *name;
+       u32 id;
+       u32 msr;
+};
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       int ret;
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct via_cputemp_data *data = dev_get_drvdata(dev);
+
+       if (attr->index == SHOW_NAME)
+               ret = sprintf(buf, "%s\n", data->name);
+       else    /* show label */
+               ret = sprintf(buf, "Core %d\n", data->id);
+       return ret;
+}
+
+static ssize_t show_temp(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       struct via_cputemp_data *data = dev_get_drvdata(dev);
+       u32 eax, edx;
+       int err;
+
+       err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+       if (err)
+               return -EAGAIN;
+
+       return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
+                         SHOW_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+
+static struct attribute *via_cputemp_attributes[] = {
+       &sensor_dev_attr_name.dev_attr.attr,
+       &sensor_dev_attr_temp1_label.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group via_cputemp_group = {
+       .attrs = via_cputemp_attributes,
+};
+
+static int __devinit via_cputemp_probe(struct platform_device *pdev)
+{
+       struct via_cputemp_data *data;
+       struct cpuinfo_x86 *c = &cpu_data(pdev->id);
+       int err;
+       u32 eax, edx;
+
+       data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               dev_err(&pdev->dev, "Out of memory\n");
+               goto exit;
+       }
+
+       data->id = pdev->id;
+       data->name = "via_cputemp";
+
+       switch (c->x86_model) {
+       case 0xA:
+               /* C7 A */
+       case 0xD:
+               /* C7 D */
+               data->msr = 0x1169;
+               break;
+       case 0xF:
+               /* Nano */
+               data->msr = 0x1423;
+               break;
+       default:
+               err = -ENODEV;
+               goto exit_free;
+       }
+
+       /* test if we can access the TEMPERATURE MSR */
+       err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+       if (err) {
+               dev_err(&pdev->dev,
+                       "Unable to access TEMPERATURE MSR, giving up\n");
+               goto exit_free;
+       }
+
+       platform_set_drvdata(pdev, data);
+
+       err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group);
+       if (err)
+               goto exit_free;
+
+       data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               dev_err(&pdev->dev, "Class registration failed (%d)\n",
+                       err);
+               goto exit_remove;
+       }
+
+       return 0;
+
+exit_remove:
+       sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
+exit_free:
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+exit:
+       return err;
+}
+
+static int __devexit via_cputemp_remove(struct platform_device *pdev)
+{
+       struct via_cputemp_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+       return 0;
+}
+
+static struct platform_driver via_cputemp_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = DRVNAME,
+       },
+       .probe = via_cputemp_probe,
+       .remove = __devexit_p(via_cputemp_remove),
+};
+
+struct pdev_entry {
+       struct list_head list;
+       struct platform_device *pdev;
+       unsigned int cpu;
+};
+
+static LIST_HEAD(pdev_list);
+static DEFINE_MUTEX(pdev_list_mutex);
+
+static int __cpuinit via_cputemp_device_add(unsigned int cpu)
+{
+       int err;
+       struct platform_device *pdev;
+       struct pdev_entry *pdev_entry;
+
+       pdev = platform_device_alloc(DRVNAME, cpu);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
+       if (!pdev_entry) {
+               err = -ENOMEM;
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_free;
+       }
+
+       pdev_entry->pdev = pdev;
+       pdev_entry->cpu = cpu;
+       mutex_lock(&pdev_list_mutex);
+       list_add_tail(&pdev_entry->list, &pdev_list);
+       mutex_unlock(&pdev_list_mutex);
+
+       return 0;
+
+exit_device_free:
+       kfree(pdev_entry);
+exit_device_put:
+       platform_device_put(pdev);
+exit:
+       return err;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void via_cputemp_device_remove(unsigned int cpu)
+{
+       struct pdev_entry *p, *n;
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               if (p->cpu == cpu) {
+                       platform_device_unregister(p->pdev);
+                       list_del(&p->list);
+                       kfree(p);
+               }
+       }
+       mutex_unlock(&pdev_list_mutex);
+}
+
+static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb,
+                                unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long) hcpu;
+
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+               via_cputemp_device_add(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               via_cputemp_device_remove(cpu);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block via_cputemp_cpu_notifier __refdata = {
+       .notifier_call = via_cputemp_cpu_callback,
+};
+#endif                         /* !CONFIG_HOTPLUG_CPU */
+
+static int __init via_cputemp_init(void)
+{
+       int i, err;
+       struct pdev_entry *p, *n;
+
+       if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
+               printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       err = platform_driver_register(&via_cputemp_driver);
+       if (err)
+               goto exit;
+
+       for_each_online_cpu(i) {
+               struct cpuinfo_x86 *c = &cpu_data(i);
+
+               if (c->x86 != 6)
+                       continue;
+
+               if (c->x86_model < 0x0a)
+                       continue;
+
+               if (c->x86_model > 0x0f) {
+                       printk(KERN_WARNING DRVNAME ": Unknown CPU "
+                               "model 0x%x\n", c->x86_model);
+                       continue;
+               }
+
+               err = via_cputemp_device_add(i);
+               if (err)
+                       goto exit_devices_unreg;
+       }
+       if (list_empty(&pdev_list)) {
+               err = -ENODEV;
+               goto exit_driver_unreg;
+       }
+
+#ifdef CONFIG_HOTPLUG_CPU
+       register_hotcpu_notifier(&via_cputemp_cpu_notifier);
+#endif
+       return 0;
+
+exit_devices_unreg:
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               platform_device_unregister(p->pdev);
+               list_del(&p->list);
+               kfree(p);
+       }
+       mutex_unlock(&pdev_list_mutex);
+exit_driver_unreg:
+       platform_driver_unregister(&via_cputemp_driver);
+exit:
+       return err;
+}
+
+static void __exit via_cputemp_exit(void)
+{
+       struct pdev_entry *p, *n;
+#ifdef CONFIG_HOTPLUG_CPU
+       unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
+#endif
+       mutex_lock(&pdev_list_mutex);
+       list_for_each_entry_safe(p, n, &pdev_list, list) {
+               platform_device_unregister(p->pdev);
+               list_del(&p->list);
+               kfree(p);
+       }
+       mutex_unlock(&pdev_list_mutex);
+       platform_driver_unregister(&via_cputemp_driver);
+}
+
+MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
+MODULE_DESCRIPTION("VIA CPU temperature monitor");
+MODULE_LICENSE("GPL");
+
+module_init(via_cputemp_init)
+module_exit(via_cputemp_exit)
index b257c72..38e2805 100644 (file)
@@ -1135,6 +1135,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
                "W83687THF",
        };
 
+       sio_data->sioaddr = sioaddr;
        superio_enter(sio_data);
        val = force_id ? force_id : superio_inb(sio_data, DEVID);
        switch (val) {
@@ -1177,7 +1178,6 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
        }
 
        err = 0;
-       sio_data->sioaddr = sioaddr;
        pr_info(DRVNAME ": Found %s chip at %#x\n",
                names[sio_data->type], *addr);
 
index 1f20a04..dd25300 100644 (file)
@@ -81,7 +81,7 @@ static u8 i7300_idle_thrtctl_saved;
 static u8 i7300_idle_thrtlow_saved;
 static u32 i7300_idle_mc_saved;
 
-static cpumask_t idle_cpumask;
+static cpumask_var_t idle_cpumask;
 static ktime_t start_ktime;
 static unsigned long avg_idle_us;
 
@@ -459,9 +459,9 @@ static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
        spin_lock_irqsave(&i7300_idle_lock, flags);
        if (val == IDLE_START) {
 
-               cpu_set(smp_processor_id(), idle_cpumask);
+               cpumask_set_cpu(smp_processor_id(), idle_cpumask);
 
-               if (cpus_weight(idle_cpumask) != num_online_cpus())
+               if (cpumask_weight(idle_cpumask) != num_online_cpus())
                        goto end;
 
                now_ktime = ktime_get();
@@ -478,8 +478,8 @@ static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
                i7300_idle_ioat_start();
 
        } else if (val == IDLE_END) {
-               cpu_clear(smp_processor_id(), idle_cpumask);
-               if (cpus_weight(idle_cpumask) == (num_online_cpus() - 1)) {
+               cpumask_clear_cpu(smp_processor_id(), idle_cpumask);
+               if (cpumask_weight(idle_cpumask) == (num_online_cpus() - 1)) {
                        /* First CPU coming out of idle */
                        u64 idle_duration_us;
 
@@ -553,7 +553,6 @@ struct debugfs_file_info {
 static int __init i7300_idle_init(void)
 {
        spin_lock_init(&i7300_idle_lock);
-       cpus_clear(idle_cpumask);
        total_us = 0;
 
        if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev, forceload))
@@ -565,6 +564,9 @@ static int __init i7300_idle_init(void)
        if (i7300_idle_ioat_init())
                return -ENODEV;
 
+       if (!zalloc_cpumask_var(&idle_cpumask, GFP_KERNEL))
+               return -ENOMEM;
+
        debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
        if (debugfs_dir) {
                int i = 0;
@@ -589,6 +591,7 @@ static int __init i7300_idle_init(void)
 static void __exit i7300_idle_exit(void)
 {
        idle_notifier_unregister(&i7300_idle_nb);
+       free_cpumask_var(idle_cpumask);
 
        if (debugfs_dir) {
                int i = 0;
index e4f599f..8a0e1ec 100644 (file)
@@ -229,6 +229,12 @@ config LEDS_PWM
        help
          This option enables support for pwm driven LEDs
 
+config LEDS_REGULATOR
+       tristate "REGULATOR driven LED support"
+       depends on LEDS_CLASS && REGULATOR
+       help
+         This option enables support for regulator driven LEDs.
+
 config LEDS_BD2802
        tristate "LED driver for BD2802 RGB LED"
        depends on LEDS_CLASS && I2C
@@ -236,6 +242,33 @@ config LEDS_BD2802
          This option enables support for BD2802GU RGB LED driver chips
          accessed via the I2C bus.
 
+config LEDS_INTEL_SS4200
+       tristate "LED driver for Intel NAS SS4200 series"
+       depends on LEDS_CLASS && PCI && DMI
+       help
+         This option enables support for the Intel SS4200 series of
+         Network Attached Storage servers.  You may control the hard
+         drive or power LEDs on the front panel.  Using this driver
+         can stop the front LED from blinking after startup.
+
+config LEDS_LT3593
+       tristate "LED driver for LT3593 controllers"
+       depends on LEDS_CLASS && GENERIC_GPIO
+       help
+         This option enables support for LEDs driven by a Linear Technology
+         LT3593 controller. This controller uses a special one-wire pulse
+         coding protocol to set the brightness.
+
+config LEDS_ADP5520
+       tristate "LED Support for ADP5520/ADP5501 PMIC"
+       depends on LEDS_CLASS && PMIC_ADP5520
+       help
+         This option enables support for on-chip LED drivers found
+         on Analog Devices ADP5520/ADP5501 PMICs.
+
+         To compile this driver as a module, choose M here: the module will
+         be called leds-adp5520.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
index 46d7270..9e63869 100644 (file)
@@ -29,6 +29,10 @@ obj-$(CONFIG_LEDS_DA903X)            += leds-da903x.o
 obj-$(CONFIG_LEDS_WM831X_STATUS)       += leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)              += leds-wm8350.o
 obj-$(CONFIG_LEDS_PWM)                 += leds-pwm.o
+obj-$(CONFIG_LEDS_REGULATOR)           += leds-regulator.o
+obj-$(CONFIG_LEDS_INTEL_SS4200)                += leds-ss4200.o
+obj-$(CONFIG_LEDS_LT3593)              += leds-lt3593.o
+obj-$(CONFIG_LEDS_ADP5520)             += leds-adp5520.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
new file mode 100644 (file)
index 0000000..a8f3159
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * LEDs driver for Analog Devices ADP5520/ADP5501 MFD PMICs
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Loosely derived from leds-da903x:
+ * Copyright (C) 2008 Compulab, Ltd.
+ *     Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ *     Eric Miao <eric.miao@marvell.com>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/adp5520.h>
+
+struct adp5520_led {
+       struct led_classdev     cdev;
+       struct work_struct      work;
+       struct device           *master;
+       enum led_brightness     new_brightness;
+       int                     id;
+       int                     flags;
+};
+
+static void adp5520_led_work(struct work_struct *work)
+{
+       struct adp5520_led *led = container_of(work, struct adp5520_led, work);
+       adp5520_write(led->master, ADP5520_LED1_CURRENT + led->id - 1,
+                        led->new_brightness >> 2);
+}
+
+static void adp5520_led_set(struct led_classdev *led_cdev,
+                          enum led_brightness value)
+{
+       struct adp5520_led *led;
+
+       led = container_of(led_cdev, struct adp5520_led, cdev);
+       led->new_brightness = value;
+       schedule_work(&led->work);
+}
+
+static int adp5520_led_setup(struct adp5520_led *led)
+{
+       struct device *dev = led->master;
+       int flags = led->flags;
+       int ret = 0;
+
+       switch (led->id) {
+       case FLAG_ID_ADP5520_LED1_ADP5501_LED0:
+               ret |= adp5520_set_bits(dev, ADP5520_LED_TIME,
+                                       (flags >> ADP5520_FLAG_OFFT_SHIFT) &
+                                       ADP5520_FLAG_OFFT_MASK);
+               ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+                                       ADP5520_LED1_EN);
+               break;
+       case FLAG_ID_ADP5520_LED2_ADP5501_LED1:
+               ret |= adp5520_set_bits(dev,  ADP5520_LED_TIME,
+                                       ((flags >> ADP5520_FLAG_OFFT_SHIFT) &
+                                       ADP5520_FLAG_OFFT_MASK) << 2);
+               ret |= adp5520_clr_bits(dev, ADP5520_LED_CONTROL,
+                                        ADP5520_R3_MODE);
+               ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+                                       ADP5520_LED2_EN);
+               break;
+       case FLAG_ID_ADP5520_LED3_ADP5501_LED2:
+               ret |= adp5520_set_bits(dev,  ADP5520_LED_TIME,
+                                       ((flags >> ADP5520_FLAG_OFFT_SHIFT) &
+                                       ADP5520_FLAG_OFFT_MASK) << 4);
+               ret |= adp5520_clr_bits(dev, ADP5520_LED_CONTROL,
+                                       ADP5520_C3_MODE);
+               ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+                                       ADP5520_LED3_EN);
+               break;
+       }
+
+       return ret;
+}
+
+static int __devinit adp5520_led_prepare(struct platform_device *pdev)
+{
+       struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+       struct device *dev = pdev->dev.parent;
+       int ret = 0;
+
+       ret |= adp5520_write(dev, ADP5520_LED1_CURRENT, 0);
+       ret |= adp5520_write(dev, ADP5520_LED2_CURRENT, 0);
+       ret |= adp5520_write(dev, ADP5520_LED3_CURRENT, 0);
+       ret |= adp5520_write(dev, ADP5520_LED_TIME, pdata->led_on_time << 6);
+       ret |= adp5520_write(dev, ADP5520_LED_FADE, FADE_VAL(pdata->fade_in,
+                pdata->fade_out));
+
+       return ret;
+}
+
+static int __devinit adp5520_led_probe(struct platform_device *pdev)
+{
+       struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+       struct adp5520_led *led, *led_dat;
+       struct led_info *cur_led;
+       int ret, i;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               return -ENODEV;
+       }
+
+       if (pdata->num_leds > ADP5520_01_MAXLEDS) {
+               dev_err(&pdev->dev, "can't handle more than %d LEDS\n",
+                                ADP5520_01_MAXLEDS);
+               return -EFAULT;
+       }
+
+       led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
+       if (led == NULL) {
+               dev_err(&pdev->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       ret = adp5520_led_prepare(pdev);
+
+       if (ret) {
+               dev_err(&pdev->dev, "failed to write\n");
+               goto err_free;
+       }
+
+       for (i = 0; i < pdata->num_leds; ++i) {
+               cur_led = &pdata->leds[i];
+               led_dat = &led[i];
+
+               led_dat->cdev.name = cur_led->name;
+               led_dat->cdev.default_trigger = cur_led->default_trigger;
+               led_dat->cdev.brightness_set = adp5520_led_set;
+               led_dat->cdev.brightness = LED_OFF;
+
+               if (cur_led->flags & ADP5520_FLAG_LED_MASK)
+                       led_dat->flags = cur_led->flags;
+               else
+                       led_dat->flags = i + 1;
+
+               led_dat->id = led_dat->flags & ADP5520_FLAG_LED_MASK;
+
+               led_dat->master = pdev->dev.parent;
+               led_dat->new_brightness = LED_OFF;
+
+               INIT_WORK(&led_dat->work, adp5520_led_work);
+
+               ret = led_classdev_register(led_dat->master, &led_dat->cdev);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to register LED %d\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               ret = adp5520_led_setup(led_dat);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to write\n");
+                       i++;
+                       goto err;
+               }
+       }
+
+       platform_set_drvdata(pdev, led);
+       return 0;
+
+err:
+       if (i > 0) {
+               for (i = i - 1; i >= 0; i--) {
+                       led_classdev_unregister(&led[i].cdev);
+                       cancel_work_sync(&led[i].work);
+               }
+       }
+
+err_free:
+       kfree(led);
+       return ret;
+}
+
+static int __devexit adp5520_led_remove(struct platform_device *pdev)
+{
+       struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+       struct adp5520_led *led;
+       int i;
+
+       led = platform_get_drvdata(pdev);
+
+       adp5520_clr_bits(led->master, ADP5520_LED_CONTROL,
+                ADP5520_LED1_EN | ADP5520_LED2_EN | ADP5520_LED3_EN);
+
+       for (i = 0; i < pdata->num_leds; i++) {
+               led_classdev_unregister(&led[i].cdev);
+               cancel_work_sync(&led[i].work);
+       }
+
+       kfree(led);
+       return 0;
+}
+
+static struct platform_driver adp5520_led_driver = {
+       .driver = {
+               .name   = "adp5520-led",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = adp5520_led_probe,
+       .remove         = __devexit_p(adp5520_led_remove),
+};
+
+static int __init adp5520_led_init(void)
+{
+       return platform_driver_register(&adp5520_led_driver);
+}
+module_init(adp5520_led_init);
+
+static void __exit adp5520_led_exit(void)
+{
+       platform_driver_unregister(&adp5520_led_driver);
+}
+module_exit(adp5520_led_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:adp5520-led");
index 731d4ee..f59ffad 100644 (file)
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/string.h>
+#include <linux/pci.h>
 
 static int force = 0;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
 
+#define MSR_LBAR_GPIO          0x5140000C
+#define CS5535_GPIO_SIZE       256
+
+static u32 gpio_base;
+
+static struct pci_device_id divil_pci[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+       { } /* NULL entry */
+};
+MODULE_DEVICE_TABLE(pci, divil_pci);
+
 struct alix_led {
        struct led_classdev cdev;
        unsigned short port;
@@ -30,9 +43,9 @@ static void alix_led_set(struct led_classdev *led_cdev,
                container_of(led_cdev, struct alix_led, cdev);
 
        if (brightness)
-               outl(led_dev->on_value, led_dev->port);
+               outl(led_dev->on_value, gpio_base + led_dev->port);
        else
-               outl(led_dev->off_value, led_dev->port);
+               outl(led_dev->off_value, gpio_base + led_dev->port);
 }
 
 static struct alix_led alix_leds[] = {
@@ -41,7 +54,7 @@ static struct alix_led alix_leds[] = {
                        .name = "alix:1",
                        .brightness_set = alix_led_set,
                },
-               .port = 0x6100,
+               .port = 0x00,
                .on_value = 1 << 22,
                .off_value = 1 << 6,
        },
@@ -50,7 +63,7 @@ static struct alix_led alix_leds[] = {
                        .name = "alix:2",
                        .brightness_set = alix_led_set,
                },
-               .port = 0x6180,
+               .port = 0x80,
                .on_value = 1 << 25,
                .off_value = 1 << 9,
        },
@@ -59,7 +72,7 @@ static struct alix_led alix_leds[] = {
                        .name = "alix:3",
                        .brightness_set = alix_led_set,
                },
-               .port = 0x6180,
+               .port = 0x80,
                .on_value = 1 << 27,
                .off_value = 1 << 11,
        },
@@ -101,64 +114,104 @@ static struct platform_driver alix_led_driver = {
        },
 };
 
-static int __init alix_present(void)
+static int __init alix_present(unsigned long bios_phys,
+                               const char *alix_sig,
+                               size_t alix_sig_len)
 {
-       const unsigned long bios_phys = 0x000f0000;
        const size_t bios_len = 0x00010000;
-       const char alix_sig[] = "PC Engines ALIX.";
-       const size_t alix_sig_len = sizeof(alix_sig) - 1;
-
        const char *bios_virt;
        const char *scan_end;
        const char *p;
-       int ret = 0;
+       char name[64];
 
        if (force) {
                printk(KERN_NOTICE "%s: forced to skip BIOS test, "
                       "assume system has ALIX.2 style LEDs\n",
                       KBUILD_MODNAME);
-               ret = 1;
-               goto out;
+               return 1;
        }
 
        bios_virt = phys_to_virt(bios_phys);
        scan_end = bios_virt + bios_len - (alix_sig_len + 2);
        for (p = bios_virt; p < scan_end; p++) {
                const char *tail;
+               char *a;
 
-               if (memcmp(p, alix_sig, alix_sig_len) != 0) {
+               if (memcmp(p, alix_sig, alix_sig_len) != 0)
                        continue;
-               }
+
+               memcpy(name, p, sizeof(name));
+
+               /* remove the first \0 character from string */
+               a = strchr(name, '\0');
+               if (a)
+                       *a = ' ';
+
+               /* cut the string at a newline */
+               a = strchr(name, '\r');
+               if (a)
+                       *a = '\0';
 
                tail = p + alix_sig_len;
-               if ((tail[0] == '2' || tail[0] == '3') && tail[1] == '\0') {
+               if ((tail[0] == '2' || tail[0] == '3')) {
                        printk(KERN_INFO
                               "%s: system is recognized as \"%s\"\n",
-                              KBUILD_MODNAME, p);
-                       ret = 1;
-                       break;
+                              KBUILD_MODNAME, name);
+                       return 1;
                }
        }
 
-out:
-       return ret;
+       return 0;
 }
 
 static struct platform_device *pdev;
 
-static int __init alix_led_init(void)
+static int __init alix_pci_led_init(void)
 {
-       int ret;
+       u32 low, hi;
 
-       if (!alix_present()) {
-               ret = -ENODEV;
-               goto out;
+       if (pci_dev_present(divil_pci) == 0) {
+               printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
+               return -ENODEV;
        }
 
-       /* enable output on GPIO for LED 1,2,3 */
-       outl(1 << 6, 0x6104);
-       outl(1 << 9, 0x6184);
-       outl(1 << 11, 0x6184);
+       /* Grab the GPIO I/O range */
+       rdmsr(MSR_LBAR_GPIO, low, hi);
+
+       /* Check the mask and whether GPIO is enabled (sanity check) */
+       if (hi != 0x0000f001) {
+               printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
+               return -ENODEV;
+       }
+
+       /* Mask off the IO base address */
+       gpio_base = low & 0x0000ff00;
+
+       if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
+               printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
+               return -ENODEV;
+       }
+
+       /* Set GPIO function to output */
+       outl(1 << 6, gpio_base + 0x04);
+       outl(1 << 9, gpio_base + 0x84);
+       outl(1 << 11, gpio_base + 0x84);
+
+       return 0;
+}
+
+static int __init alix_led_init(void)
+{
+       int ret = -ENODEV;
+       const char tinybios_sig[] = "PC Engines ALIX.";
+       const char coreboot_sig[] = "PC Engines\0ALIX.";
+
+       if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
+           alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
+               ret = alix_pci_led_init();
+
+       if (ret < 0)
+               return ret;
 
        pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
        if (!IS_ERR(pdev)) {
@@ -168,7 +221,6 @@ static int __init alix_led_init(void)
        } else
                ret = PTR_ERR(pdev);
 
-out:
        return ret;
 }
 
@@ -176,6 +228,7 @@ static void __exit alix_led_exit(void)
 {
        platform_device_unregister(pdev);
        platform_driver_unregister(&alix_led_driver);
+       release_region(gpio_base, CS5535_GPIO_SIZE);
 }
 
 module_init(alix_led_init);
index 8816806..da5fb01 100644 (file)
@@ -31,7 +31,7 @@ static struct led_classdev qube_front_led = {
        .name                   = "qube::front",
        .brightness             = LED_FULL,
        .brightness_set         = qube_front_led_set,
-       .default_trigger        = "ide-disk",
+       .default_trigger        = "default-on",
 };
 
 static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
@@ -43,7 +43,7 @@ static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
        if (!res)
                return -EBUSY;
 
-       led_port = ioremap(res->start, res->end - res->start + 1);
+       led_port = ioremap(res->start, resource_size(res));
        if (!led_port)
                return -ENOMEM;
 
index defc212..438d483 100644 (file)
@@ -84,7 +84,7 @@ static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
        if (!res)
                return -EBUSY;
 
-       led_port = ioremap(res->start, res->end - res->start + 1);
+       led_port = ioremap(res->start, resource_size(res));
        if (!led_port)
                return -ENOMEM;
 
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
new file mode 100644 (file)
index 0000000..fee40a8
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * LEDs driver for LT3593 controllers
+ *
+ * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on leds-gpio.c,
+ *
+ *   Copyright (C) 2007 8D Technologies inc.
+ *   Raphael Assenat <raph@8d.com>
+ *   Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+struct lt3593_led_data {
+       struct led_classdev cdev;
+       unsigned gpio;
+       struct work_struct work;
+       u8 new_level;
+};
+
+static void lt3593_led_work(struct work_struct *work)
+{
+       int pulses;
+       struct lt3593_led_data *led_dat =
+               container_of(work, struct lt3593_led_data, work);
+
+       /*
+        * The LT3593 resets its internal current level register to the maximum
+        * level on the first falling edge on the control pin. Each following
+        * falling edge decreases the current level by 625uA. Up to 32 pulses
+        * can be sent, so the maximum power reduction is 20mA.
+        * After a timeout of 128us, the value is taken from the register and
+        * applied is to the output driver.
+        */
+
+       if (led_dat->new_level == 0) {
+               gpio_set_value_cansleep(led_dat->gpio, 0);
+               return;
+       }
+
+       pulses = 32 - (led_dat->new_level * 32) / 255;
+
+       if (pulses == 0) {
+               gpio_set_value_cansleep(led_dat->gpio, 0);
+               mdelay(1);
+               gpio_set_value_cansleep(led_dat->gpio, 1);
+               return;
+       }
+
+       gpio_set_value_cansleep(led_dat->gpio, 1);
+
+       while (pulses--) {
+               gpio_set_value_cansleep(led_dat->gpio, 0);
+               udelay(1);
+               gpio_set_value_cansleep(led_dat->gpio, 1);
+               udelay(1);
+       }
+}
+
+static void lt3593_led_set(struct led_classdev *led_cdev,
+       enum led_brightness value)
+{
+       struct lt3593_led_data *led_dat =
+               container_of(led_cdev, struct lt3593_led_data, cdev);
+
+       led_dat->new_level = value;
+       schedule_work(&led_dat->work);
+}
+
+static int __devinit create_lt3593_led(const struct gpio_led *template,
+       struct lt3593_led_data *led_dat, struct device *parent)
+{
+       int ret, state;
+
+       /* skip leds on GPIOs that aren't available */
+       if (!gpio_is_valid(template->gpio)) {
+               printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
+                               KBUILD_MODNAME, template->gpio, template->name);
+               return 0;
+       }
+
+       ret = gpio_request(template->gpio, template->name);
+       if (ret < 0)
+               return ret;
+
+       led_dat->cdev.name = template->name;
+       led_dat->cdev.default_trigger = template->default_trigger;
+       led_dat->gpio = template->gpio;
+
+       led_dat->cdev.brightness_set = lt3593_led_set;
+
+       state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+       led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
+
+       if (!template->retain_state_suspended)
+               led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+       ret = gpio_direction_output(led_dat->gpio, state);
+       if (ret < 0)
+               goto err;
+
+       INIT_WORK(&led_dat->work, lt3593_led_work);
+
+       ret = led_classdev_register(parent, &led_dat->cdev);
+       if (ret < 0)
+               goto err;
+
+       printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n",
+               KBUILD_MODNAME, template->name, template->gpio);
+
+       return 0;
+
+err:
+       gpio_free(led_dat->gpio);
+       return ret;
+}
+
+static void delete_lt3593_led(struct lt3593_led_data *led)
+{
+       if (!gpio_is_valid(led->gpio))
+               return;
+
+       led_classdev_unregister(&led->cdev);
+       cancel_work_sync(&led->work);
+       gpio_free(led->gpio);
+}
+
+static int __devinit lt3593_led_probe(struct platform_device *pdev)
+{
+       struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+       struct lt3593_led_data *leds_data;
+       int i, ret = 0;
+
+       if (!pdata)
+               return -EBUSY;
+
+       leds_data = kzalloc(sizeof(struct lt3593_led_data) * pdata->num_leds,
+                               GFP_KERNEL);
+       if (!leds_data)
+               return -ENOMEM;
+
+       for (i = 0; i < pdata->num_leds; i++) {
+               ret = create_lt3593_led(&pdata->leds[i], &leds_data[i],
+                                     &pdev->dev);
+               if (ret < 0)
+                       goto err;
+       }
+
+       platform_set_drvdata(pdev, leds_data);
+
+       return 0;
+
+err:
+       for (i = i - 1; i >= 0; i--)
+               delete_lt3593_led(&leds_data[i]);
+
+       kfree(leds_data);
+
+       return ret;
+}
+
+static int __devexit lt3593_led_remove(struct platform_device *pdev)
+{
+       int i;
+       struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+       struct lt3593_led_data *leds_data;
+
+       leds_data = platform_get_drvdata(pdev);
+
+       for (i = 0; i < pdata->num_leds; i++)
+               delete_lt3593_led(&leds_data[i]);
+
+       kfree(leds_data);
+
+       return 0;
+}
+
+static struct platform_driver lt3593_led_driver = {
+       .probe          = lt3593_led_probe,
+       .remove         = __devexit_p(lt3593_led_remove),
+       .driver         = {
+               .name   = "leds-lt3593",
+               .owner  = THIS_MODULE,
+       },
+};
+
+MODULE_ALIAS("platform:leds-lt3593");
+
+static int __init lt3593_led_init(void)
+{
+       return platform_driver_register(&lt3593_led_driver);
+}
+
+static void __exit lt3593_led_exit(void)
+{
+       platform_driver_unregister(&lt3593_led_driver);
+}
+
+module_init(lt3593_led_init);
+module_exit(lt3593_led_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("LED driver for LT3593 controllers");
+MODULE_LICENSE("GPL");
index cdfdc87..88b1dd0 100644 (file)
@@ -27,7 +27,6 @@ struct led_pwm_data {
        struct pwm_device       *pwm;
        unsigned int            active_low;
        unsigned int            period;
-       unsigned int            max_brightness;
 };
 
 static void led_pwm_set(struct led_classdev *led_cdev,
@@ -35,7 +34,7 @@ static void led_pwm_set(struct led_classdev *led_cdev,
 {
        struct led_pwm_data *led_dat =
                container_of(led_cdev, struct led_pwm_data, cdev);
-       unsigned int max = led_dat->max_brightness;
+       unsigned int max = led_dat->cdev.max_brightness;
        unsigned int period =  led_dat->period;
 
        if (brightness == 0) {
@@ -77,10 +76,10 @@ static int led_pwm_probe(struct platform_device *pdev)
                led_dat->cdev.name = cur_led->name;
                led_dat->cdev.default_trigger = cur_led->default_trigger;
                led_dat->active_low = cur_led->active_low;
-               led_dat->max_brightness = cur_led->max_brightness;
                led_dat->period = cur_led->pwm_period_ns;
                led_dat->cdev.brightness_set = led_pwm_set;
                led_dat->cdev.brightness = LED_OFF;
+               led_dat->cdev.max_brightness = cur_led->max_brightness;
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
                ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
new file mode 100644 (file)
index 0000000..7f00de3
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * leds-regulator.c - LED class driver for regulator driven LEDs.
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * Inspired by leds-wm8350 driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+#include <linux/leds-regulator.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#define to_regulator_led(led_cdev) \
+       container_of(led_cdev, struct regulator_led, cdev)
+
+struct regulator_led {
+       struct led_classdev cdev;
+       enum led_brightness value;
+       int enabled;
+       struct mutex mutex;
+       struct work_struct work;
+
+       struct regulator *vcc;
+};
+
+static inline int led_regulator_get_max_brightness(struct regulator *supply)
+{
+       int ret;
+       int voltage = regulator_list_voltage(supply, 0);
+
+       if (voltage <= 0)
+               return 1;
+
+       /* even if regulator can't change voltages,
+        * we still assume it can change status
+        * and the LED can be turned on and off.
+        */
+       ret = regulator_set_voltage(supply, voltage, voltage);
+       if (ret < 0)
+               return 1;
+
+       return regulator_count_voltages(supply);
+}
+
+static int led_regulator_get_voltage(struct regulator *supply,
+               enum led_brightness brightness)
+{
+       if (brightness == 0)
+               return -EINVAL;
+
+       return regulator_list_voltage(supply, brightness - 1);
+}
+
+
+static void regulator_led_enable(struct regulator_led *led)
+{
+       int ret;
+
+       if (led->enabled)
+               return;
+
+       ret = regulator_enable(led->vcc);
+       if (ret != 0) {
+               dev_err(led->cdev.dev, "Failed to enable vcc: %d\n", ret);
+               return;
+       }
+
+       led->enabled = 1;
+}
+
+static void regulator_led_disable(struct regulator_led *led)
+{
+       int ret;
+
+       if (!led->enabled)
+               return;
+
+       ret = regulator_disable(led->vcc);
+       if (ret != 0) {
+               dev_err(led->cdev.dev, "Failed to disable vcc: %d\n", ret);
+               return;
+       }
+
+       led->enabled = 0;
+}
+
+static void regulator_led_set_value(struct regulator_led *led)
+{
+       int voltage;
+       int ret;
+
+       mutex_lock(&led->mutex);
+
+       if (led->value == LED_OFF) {
+               regulator_led_disable(led);
+               goto out;
+       }
+
+       if (led->cdev.max_brightness > 1) {
+               voltage = led_regulator_get_voltage(led->vcc, led->value);
+               dev_dbg(led->cdev.dev, "brightness: %d voltage: %d\n",
+                               led->value, voltage);
+
+               ret = regulator_set_voltage(led->vcc, voltage, voltage);
+               if (ret != 0)
+                       dev_err(led->cdev.dev, "Failed to set voltage %d: %d\n",
+                               voltage, ret);
+       }
+
+       regulator_led_enable(led);
+
+out:
+       mutex_unlock(&led->mutex);
+}
+
+static void led_work(struct work_struct *work)
+{
+       struct regulator_led *led;
+
+       led = container_of(work, struct regulator_led, work);
+       regulator_led_set_value(led);
+}
+
+static void regulator_led_brightness_set(struct led_classdev *led_cdev,
+                          enum led_brightness value)
+{
+       struct regulator_led *led = to_regulator_led(led_cdev);
+
+       led->value = value;
+       schedule_work(&led->work);
+}
+
+static int __devinit regulator_led_probe(struct platform_device *pdev)
+{
+       struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
+       struct regulator_led *led;
+       struct regulator *vcc;
+       int ret = 0;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "no platform data\n");
+               return -ENODEV;
+       }
+
+       vcc = regulator_get_exclusive(&pdev->dev, "vled");
+       if (IS_ERR(vcc)) {
+               dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
+               return PTR_ERR(vcc);
+       }
+
+       led = kzalloc(sizeof(*led), GFP_KERNEL);
+       if (led == NULL) {
+               ret = -ENOMEM;
+               goto err_vcc;
+       }
+
+       led->cdev.max_brightness = led_regulator_get_max_brightness(vcc);
+       if (pdata->brightness > led->cdev.max_brightness) {
+               dev_err(&pdev->dev, "Invalid default brightness %d\n",
+                               pdata->brightness);
+               ret = -EINVAL;
+               goto err_led;
+       }
+       led->value = pdata->brightness;
+
+       led->cdev.brightness_set = regulator_led_brightness_set;
+       led->cdev.name = pdata->name;
+       led->cdev.flags |= LED_CORE_SUSPENDRESUME;
+       led->vcc = vcc;
+
+       mutex_init(&led->mutex);
+       INIT_WORK(&led->work, led_work);
+
+       platform_set_drvdata(pdev, led);
+
+       ret = led_classdev_register(&pdev->dev, &led->cdev);
+       if (ret < 0) {
+               cancel_work_sync(&led->work);
+               goto err_led;
+       }
+
+       /* to expose the default value to userspace */
+       led->cdev.brightness = led->value;
+
+       /* Set the default led status */
+       regulator_led_set_value(led);
+
+       return 0;
+
+err_led:
+       kfree(led);
+err_vcc:
+       regulator_put(vcc);
+       return ret;
+}
+
+static int __devexit regulator_led_remove(struct platform_device *pdev)
+{
+       struct regulator_led *led = platform_get_drvdata(pdev);
+
+       led_classdev_unregister(&led->cdev);
+       cancel_work_sync(&led->work);
+       regulator_led_disable(led);
+       regulator_put(led->vcc);
+       kfree(led);
+       return 0;
+}
+
+static struct platform_driver regulator_led_driver = {
+       .driver = {
+                  .name  = "leds-regulator",
+                  .owner = THIS_MODULE,
+                  },
+       .probe  = regulator_led_probe,
+       .remove = __devexit_p(regulator_led_remove),
+};
+
+static int __init regulator_led_init(void)
+{
+       return platform_driver_register(&regulator_led_driver);
+}
+module_init(regulator_led_init);
+
+static void __exit regulator_led_exit(void)
+{
+       platform_driver_unregister(&regulator_led_driver);
+}
+module_exit(regulator_led_exit);
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("Regulator driven LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-regulator");
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
new file mode 100644 (file)
index 0000000..97f0498
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * SS4200-E Hardware API
+ * Copyright (c) 2009, Intel Corporation.
+ * Copyright IBM Corporation, 2009
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Dave Hansen <dave@sr71.net>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dmi.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+MODULE_AUTHOR("Rodney Girod <rgirod@confocus.com>, Dave Hansen <dave@sr71.net>");
+MODULE_DESCRIPTION("Intel NAS/Home Server ICH7 GPIO Driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * ICH7 LPC/GPIO PCI Config register offsets
+ */
+#define PMBASE         0x040
+#define GPIO_BASE      0x048
+#define GPIO_CTRL      0x04c
+#define GPIO_EN                0x010
+
+/*
+ * The ICH7 GPIO register block is 64 bytes in size.
+ */
+#define ICH7_GPIO_SIZE 64
+
+/*
+ * Define register offsets within the ICH7 register block.
+ */
+#define GPIO_USE_SEL   0x000
+#define GP_IO_SEL      0x004
+#define GP_LVL         0x00c
+#define GPO_BLINK      0x018
+#define GPI_INV                0x030
+#define GPIO_USE_SEL2  0x034
+#define GP_IO_SEL2     0x038
+#define GP_LVL2                0x03c
+
+/*
+ * PCI ID of the Intel ICH7 LPC Device within which the GPIO block lives.
+ */
+static struct pci_device_id ich7_lpc_pci_id[] =
+{
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30) },
+       { } /* NULL entry */
+};
+
+MODULE_DEVICE_TABLE(pci, ich7_lpc_pci_id);
+
+static int __init ss4200_led_dmi_callback(const struct dmi_system_id *id)
+{
+       pr_info("detected '%s'\n", id->ident);
+       return 1;
+}
+
+static unsigned int __initdata nodetect;
+module_param_named(nodetect, nodetect, bool, 0);
+MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
+
+/*
+ * struct nas_led_whitelist - List of known good models
+ *
+ * Contains the known good models this driver is compatible with.
+ * When adding a new model try to be as strict as possible. This
+ * makes it possible to keep the false positives (the model is
+ * detected as working, but in reality it is not) as low as
+ * possible.
+ */
+static struct dmi_system_id __initdata nas_led_whitelist[] = {
+       {
+               .callback = ss4200_led_dmi_callback,
+               .ident = "Intel SS4200-E",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SS4200-E"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
+               }
+       },
+};
+
+/*
+ * Base I/O address assigned to the Power Management register block
+ */
+static u32 g_pm_io_base;
+
+/*
+ * Base I/O address assigned to the ICH7 GPIO register block
+ */
+static u32 nas_gpio_io_base;
+
+/*
+ * When we successfully register a region, we are returned a resource.
+ * We use these to identify which regions we need to release on our way
+ * back out.
+ */
+static struct resource *gp_gpio_resource;
+
+struct nasgpio_led {
+       char *name;
+       u32 gpio_bit;
+       struct led_classdev led_cdev;
+};
+
+/*
+ * gpio_bit(s) are the ICH7 GPIO bit assignments
+ */
+static struct nasgpio_led nasgpio_leds[] = {
+       { .name = "hdd1:blue:sata",     .gpio_bit = 0 },
+       { .name = "hdd1:amber:sata",    .gpio_bit = 1 },
+       { .name = "hdd2:blue:sata",     .gpio_bit = 2 },
+       { .name = "hdd2:amber:sata",    .gpio_bit = 3 },
+       { .name = "hdd3:blue:sata",     .gpio_bit = 4 },
+       { .name = "hdd3:amber:sata",    .gpio_bit = 5 },
+       { .name = "hdd4:blue:sata",     .gpio_bit = 6 },
+       { .name = "hdd4:amber:sata",    .gpio_bit = 7 },
+       { .name = "power:blue:power",   .gpio_bit = 27},
+       { .name = "power:amber:power",  .gpio_bit = 28},
+};
+
+#define NAS_RECOVERY   0x00000400      /* GPIO10 */
+
+static struct nasgpio_led *
+led_classdev_to_nasgpio_led(struct led_classdev *led_cdev)
+{
+       return container_of(led_cdev, struct nasgpio_led, led_cdev);
+}
+
+static struct nasgpio_led *get_led_named(char *name)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
+               if (strcmp(nasgpio_leds[i].name, name))
+                       continue;
+               return &nasgpio_leds[i];
+       }
+       return NULL;
+}
+
+/*
+ * This protects access to the gpio ports.
+ */
+static DEFINE_SPINLOCK(nasgpio_gpio_lock);
+
+/*
+ * There are two gpio ports, one for blinking and the other
+ * for power.  @port tells us if we're doing blinking or
+ * power control.
+ *
+ * Caller must hold nasgpio_gpio_lock
+ */
+static void __nasgpio_led_set_attr(struct led_classdev *led_cdev,
+                                  u32 port, u32 value)
+{
+       struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
+       u32 gpio_out;
+
+       gpio_out = inl(nas_gpio_io_base + port);
+       if (value)
+               gpio_out |= (1<<led->gpio_bit);
+       else
+               gpio_out &= ~(1<<led->gpio_bit);
+
+       outl(gpio_out, nas_gpio_io_base + port);
+}
+
+static void nasgpio_led_set_attr(struct led_classdev *led_cdev,
+                                u32 port, u32 value)
+{
+       spin_lock(&nasgpio_gpio_lock);
+       __nasgpio_led_set_attr(led_cdev, port, value);
+       spin_unlock(&nasgpio_gpio_lock);
+}
+
+u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port)
+{
+       struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
+       u32 gpio_in;
+
+       spin_lock(&nasgpio_gpio_lock);
+       gpio_in = inl(nas_gpio_io_base + port);
+       spin_unlock(&nasgpio_gpio_lock);
+       if (gpio_in & (1<<led->gpio_bit))
+               return 1;
+       return 0;
+}
+
+/*
+ * There is actual brightness control in the hardware,
+ * but it is via smbus commands and not implemented
+ * in this driver.
+ */
+static void nasgpio_led_set_brightness(struct led_classdev *led_cdev,
+                                      enum led_brightness brightness)
+{
+       u32 setting = 0;
+       if (brightness >= LED_HALF)
+               setting = 1;
+       /*
+        * Hold the lock across both operations.  This ensures
+        * consistency so that both the "turn off blinking"
+        * and "turn light off" operations complete as a set.
+        */
+       spin_lock(&nasgpio_gpio_lock);
+       /*
+        * LED class documentation asks that past blink state
+        * be disabled when brightness is turned to zero.
+        */
+       if (brightness == 0)
+               __nasgpio_led_set_attr(led_cdev, GPO_BLINK, 0);
+       __nasgpio_led_set_attr(led_cdev, GP_LVL, setting);
+       spin_unlock(&nasgpio_gpio_lock);
+}
+
+static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
+                                unsigned long *delay_on,
+                                unsigned long *delay_off)
+{
+       u32 setting = 1;
+       if (!(*delay_on == 0 && *delay_off == 0) &&
+           !(*delay_on == 500 && *delay_off == 500))
+               return -EINVAL;
+       /*
+        * These are very approximate.
+        */
+       *delay_on = 500;
+       *delay_off = 500;
+
+       nasgpio_led_set_attr(led_cdev, GPO_BLINK, setting);
+
+       return 0;
+}
+
+
+/*
+ * Initialize the ICH7 GPIO registers for NAS usage.  The BIOS should have
+ * already taken care of this, but we will do so in a non destructive manner
+ * so that we have what we need whether the BIOS did it or not.
+ */
+static int __devinit ich7_gpio_init(struct device *dev)
+{
+       int i;
+       u32 config_data = 0;
+       u32 all_nas_led = 0;
+
+       for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
+               all_nas_led |= (1<<nasgpio_leds[i].gpio_bit);
+
+       spin_lock(&nasgpio_gpio_lock);
+       /*
+        * We need to enable all of the GPIO lines used by the NAS box,
+        * so we will read the current Use Selection and add our usage
+        * to it.  This should be benign with regard to the original
+        * BIOS configuration.
+        */
+       config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
+       dev_dbg(dev, ": Data read from GPIO_USE_SEL = 0x%08x\n", config_data);
+       config_data |= all_nas_led + NAS_RECOVERY;
+       outl(config_data, nas_gpio_io_base + GPIO_USE_SEL);
+       config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
+       dev_dbg(dev, ": GPIO_USE_SEL = 0x%08x\n\n", config_data);
+
+       /*
+        * The LED GPIO outputs need to be configured for output, so we
+        * will ensure that all LED lines are cleared for output and the
+        * RECOVERY line ready for input.  This too should be benign with
+        * regard to BIOS configuration.
+        */
+       config_data = inl(nas_gpio_io_base + GP_IO_SEL);
+       dev_dbg(dev, ": Data read from GP_IO_SEL = 0x%08x\n",
+                                       config_data);
+       config_data &= ~all_nas_led;
+       config_data |= NAS_RECOVERY;
+       outl(config_data, nas_gpio_io_base + GP_IO_SEL);
+       config_data = inl(nas_gpio_io_base + GP_IO_SEL);
+       dev_dbg(dev, ": GP_IO_SEL = 0x%08x\n", config_data);
+
+       /*
+        * In our final system, the BIOS will initialize the state of all
+        * of the LEDs.  For now, we turn them all off (or Low).
+        */
+       config_data = inl(nas_gpio_io_base + GP_LVL);
+       dev_dbg(dev, ": Data read from GP_LVL = 0x%08x\n", config_data);
+       /*
+        * In our final system, the BIOS will initialize the blink state of all
+        * of the LEDs.  For now, we turn blink off for all of them.
+        */
+       config_data = inl(nas_gpio_io_base + GPO_BLINK);
+       dev_dbg(dev, ": Data read from GPO_BLINK = 0x%08x\n", config_data);
+
+       /*
+        * At this moment, I am unsure if anything needs to happen with GPI_INV
+        */
+       config_data = inl(nas_gpio_io_base + GPI_INV);
+       dev_dbg(dev, ": Data read from GPI_INV = 0x%08x\n", config_data);
+
+       spin_unlock(&nasgpio_gpio_lock);
+       return 0;
+}
+
+static void ich7_lpc_cleanup(struct device *dev)
+{
+       /*
+        * If we were given exclusive use of the GPIO
+        * I/O Address range, we must return it.
+        */
+       if (gp_gpio_resource) {
+               dev_dbg(dev, ": Releasing GPIO I/O addresses\n");
+               release_region(nas_gpio_io_base, ICH7_GPIO_SIZE);
+               gp_gpio_resource = NULL;
+       }
+}
+
+/*
+ * The OS has determined that the LPC of the Intel ICH7 Southbridge is present
+ * so we can retrive the required operational information and prepare the GPIO.
+ */
+static struct pci_dev *nas_gpio_pci_dev;
+static int __devinit ich7_lpc_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
+{
+       int status;
+       u32 gc = 0;
+
+       status = pci_enable_device(dev);
+       if (status) {
+               dev_err(&dev->dev, "pci_enable_device failed\n");
+               return -EIO;
+       }
+
+       nas_gpio_pci_dev = dev;
+       status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
+       if (status)
+               goto out;
+       g_pm_io_base &= 0x00000ff80;
+
+       status = pci_read_config_dword(dev, GPIO_CTRL, &gc);
+       if (!(GPIO_EN & gc)) {
+               status = -EEXIST;
+               dev_info(&dev->dev,
+                          "ERROR: The LPC GPIO Block has not been enabled.\n");
+               goto out;
+       }
+
+       status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base);
+       if (0 > status) {
+               dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
+               goto out;
+       }
+       dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);
+       nas_gpio_io_base &= 0x00000ffc0;
+
+       /*
+        * Insure that we have exclusive access to the GPIO I/O address range.
+        */
+       gp_gpio_resource = request_region(nas_gpio_io_base, ICH7_GPIO_SIZE,
+                                         KBUILD_MODNAME);
+       if (NULL == gp_gpio_resource) {
+               dev_info(&dev->dev,
+                        "ERROR Unable to register GPIO I/O addresses.\n");
+               status = -1;
+               goto out;
+       }
+
+       /*
+        * Initialize the GPIO for NAS/Home Server Use
+        */
+       ich7_gpio_init(&dev->dev);
+
+out:
+       if (status) {
+               ich7_lpc_cleanup(&dev->dev);
+               pci_disable_device(dev);
+       }
+       return status;
+}
+
+static void ich7_lpc_remove(struct pci_dev *dev)
+{
+       ich7_lpc_cleanup(&dev->dev);
+       pci_disable_device(dev);
+}
+
+/*
+ * pci_driver structure passed to the PCI modules
+ */
+static struct pci_driver nas_gpio_pci_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = ich7_lpc_pci_id,
+       .probe = ich7_lpc_probe,
+       .remove = ich7_lpc_remove,
+};
+
+static struct led_classdev *get_classdev_for_led_nr(int nr)
+{
+       struct nasgpio_led *nas_led = &nasgpio_leds[nr];
+       struct led_classdev *led = &nas_led->led_cdev;
+       return led;
+}
+
+
+static void set_power_light_amber_noblink(void)
+{
+       struct nasgpio_led *amber = get_led_named("power:amber:power");
+       struct nasgpio_led *blue = get_led_named("power:blue:power");
+
+       if (!amber || !blue)
+               return;
+       /*
+        * LED_OFF implies disabling future blinking
+        */
+       pr_debug("setting blue off and amber on\n");
+
+       nasgpio_led_set_brightness(&blue->led_cdev, LED_OFF);
+       nasgpio_led_set_brightness(&amber->led_cdev, LED_FULL);
+}
+
+static ssize_t nas_led_blink_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct led_classdev *led = dev_get_drvdata(dev);
+       int blinking = 0;
+       if (nasgpio_led_get_attr(led, GPO_BLINK))
+               blinking = 1;
+       return sprintf(buf, "%u\n", blinking);
+}
+
+static ssize_t nas_led_blink_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t size)
+{
+       int ret;
+       struct led_classdev *led = dev_get_drvdata(dev);
+       unsigned long blink_state;
+
+       ret = strict_strtoul(buf, 10, &blink_state);
+       if (ret)
+               return ret;
+
+       nasgpio_led_set_attr(led, GPO_BLINK, blink_state);
+
+       return size;
+}
+
+static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
+
+static int register_nasgpio_led(int led_nr)
+{
+       int ret;
+       struct nasgpio_led *nas_led = &nasgpio_leds[led_nr];
+       struct led_classdev *led = get_classdev_for_led_nr(led_nr);
+
+       led->name = nas_led->name;
+       led->brightness = LED_OFF;
+       if (nasgpio_led_get_attr(led, GP_LVL))
+               led->brightness = LED_FULL;
+       led->brightness_set = nasgpio_led_set_brightness;
+       led->blink_set = nasgpio_led_set_blink;
+       ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
+       if (ret)
+               return ret;
+       ret = device_create_file(led->dev, &dev_attr_blink);
+       if (ret)
+               led_classdev_unregister(led);
+       return ret;
+}
+
+static void unregister_nasgpio_led(int led_nr)
+{
+       struct led_classdev *led = get_classdev_for_led_nr(led_nr);
+       led_classdev_unregister(led);
+       device_remove_file(led->dev, &dev_attr_blink);
+}
+/*
+ * module load/initialization
+ */
+static int __init nas_gpio_init(void)
+{
+       int i;
+       int ret = 0;
+       int nr_devices = 0;
+
+       nr_devices = dmi_check_system(nas_led_whitelist);
+       if (nodetect) {
+               pr_info("skipping hardware autodetection\n");
+               pr_info("Please send 'dmidecode' output to dave@sr71.net\n");
+               nr_devices++;
+       }
+
+       if (nr_devices <= 0) {
+               pr_info("no LED devices found\n");
+               return -ENODEV;
+       }
+
+       pr_info("registering PCI driver\n");
+       ret = pci_register_driver(&nas_gpio_pci_driver);
+       if (ret)
+               return ret;
+       for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
+               ret = register_nasgpio_led(i);
+               if (ret)
+                       goto out_err;
+       }
+       /*
+        * When the system powers on, the BIOS leaves the power
+        * light blue and blinking.  This will turn it solid
+        * amber once the driver is loaded.
+        */
+       set_power_light_amber_noblink();
+       return 0;
+out_err:
+       for (; i >= 0; i--)
+               unregister_nasgpio_led(i);
+       pci_unregister_driver(&nas_gpio_pci_driver);
+       return ret;
+}
+
+/*
+ * module unload
+ */
+static void __exit nas_gpio_exit(void)
+{
+       int i;
+       pr_info("Unregistering driver\n");
+       for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
+               unregister_nasgpio_led(i);
+       pci_unregister_driver(&nas_gpio_pci_driver);
+}
+
+module_init(nas_gpio_init);
+module_exit(nas_gpio_exit);
index 610e914..85bc6a6 100644 (file)
@@ -1587,7 +1587,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
 {
        u8              __iomem *mem;
        int              ii;
-       unsigned long    mem_phys;
+       resource_size_t  mem_phys;
        unsigned long    port;
        u32              msize;
        u32              psize;
@@ -1677,8 +1677,8 @@ mpt_mapresources(MPT_ADAPTER *ioc)
                return -EINVAL;
        }
        ioc->memmap = mem;
-       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
-           ioc->name, mem, mem_phys));
+       dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
+           ioc->name, mem, (unsigned long long)mem_phys));
 
        ioc->mem_phys = mem_phys;
        ioc->chip = (SYSIF_REGS __iomem *)mem;
index 1a7a9fc..e3551d2 100644 (file)
@@ -203,6 +203,7 @@ config CS5535_MFGPT
 
 config CS5535_MFGPT_DEFAULT_IRQ
        int
+       depends on CS5535_MFGPT
        default 7
        help
          MFGPTs on the CS5535 require an interrupt.  The selected IRQ
index e9eae4a..1eac626 100644 (file)
@@ -391,6 +391,7 @@ static const char *const enclosure_status [] = {
        [ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
        [ENCLOSURE_STATUS_UNKNOWN] = "unknown",
        [ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+       [ENCLOSURE_STATUS_MAX] = NULL,
 };
 
 static const char *const enclosure_type [] = {
index cdb845b..06b6408 100644 (file)
@@ -516,7 +516,8 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
         * The number of functions on the card is encoded inside
         * the ocr.
         */
-       card->sdio_funcs = funcs = (ocr & 0x70000000) >> 28;
+       funcs = (ocr & 0x70000000) >> 28;
+       card->sdio_funcs = 0;
 
        /*
         * If needed, disconnect card detection pull-up resistor.
@@ -528,7 +529,7 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
        /*
         * Initialize (but don't add) all present functions.
         */
-       for (i = 0;i < funcs;i++) {
+       for (i = 0; i < funcs; i++, card->sdio_funcs++) {
                err = sdio_init_func(host->card, i + 1);
                if (err)
                        goto remove;
index d37464e..9e060c8 100644 (file)
@@ -248,12 +248,15 @@ int sdio_add_func(struct sdio_func *func)
 /*
  * Unregister a SDIO function with the driver model, and
  * (eventually) free it.
+ * This function can be called through error paths where sdio_add_func() was
+ * never executed (because a failure occurred at an earlier point).
  */
 void sdio_remove_func(struct sdio_func *func)
 {
-       if (sdio_func_present(func))
-               device_del(&func->dev);
+       if (!sdio_func_present(func))
+               return;
 
+       device_del(&func->dev);
        put_device(&func->dev);
 }
 
index 9d405b1..ce1d288 100644 (file)
@@ -44,6 +44,19 @@ config MMC_SDHCI_IO_ACCESSORS
          This is silent Kconfig symbol that is selected by the drivers that
          need to overwrite SDHCI IO memory accessors.
 
+config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+       bool
+       select MMC_SDHCI_IO_ACCESSORS
+       help
+         This option is selected by drivers running on big endian hosts
+         and performing I/O to a SDHCI controller through a bus that
+         implements a hardware byte swapper using a 32-bit datum.
+         This endian mapping mode is called "data invariance" and
+         has the effect of scrambling the addresses and formats of data
+         accessed in sizes other than the datum size.
+
+         This is the case for the Freescale eSDHC and Nintendo Wii SDHCI.
+
 config MMC_SDHCI_PCI
        tristate "SDHCI support on PCI bus"
        depends on MMC_SDHCI && PCI
@@ -75,11 +88,29 @@ config MMC_RICOH_MMC
 config MMC_SDHCI_OF
        tristate "SDHCI support on OpenFirmware platforms"
        depends on MMC_SDHCI && PPC_OF
-       select MMC_SDHCI_IO_ACCESSORS
        help
          This selects the OF support for Secure Digital Host Controller
-         Interfaces. So far, only the Freescale eSDHC controller is known
-         to exist on OF platforms.
+         Interfaces.
+
+         If unsure, say N.
+
+config MMC_SDHCI_OF_ESDHC
+       bool "SDHCI OF support for the Freescale eSDHC controller"
+       depends on MMC_SDHCI_OF
+       select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+       help
+         This selects the Freescale eSDHC controller support.
+
+         If unsure, say N.
+
+config MMC_SDHCI_OF_HLWD
+       bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+       depends on MMC_SDHCI_OF
+       select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+       help
+         This selects the Secure Digital Host Controller Interface (SDHCI)
+         found in the "Hollywood" chipset of the Nintendo Wii video game
+         console.
 
          If unsure, say N.
 
index ded4d8c..3d253dd 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_MMC_MXC)         += mxcmmc.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
 obj-$(CONFIG_MMC_RICOH_MMC)    += ricoh_mmc.o
-obj-$(CONFIG_MMC_SDHCI_OF)     += sdhci-of.o
 obj-$(CONFIG_MMC_SDHCI_PLTFM)  += sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_S3C)    += sdhci-s3c.o
 obj-$(CONFIG_MMC_WBSD)         += wbsd.o
@@ -37,6 +36,11 @@ obj-$(CONFIG_MMC_CB710)      += cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)    += via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)         += bfin_sdh.o
 
+obj-$(CONFIG_MMC_SDHCI_OF)     += sdhci-of.o
+sdhci-of-y                             := sdhci-of-core.o
+sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC)  += sdhci-of-esdhc.o
+sdhci-of-$(CONFIG_MMC_SDHCI_OF_HLWD)   += sdhci-of-hlwd.o
+
 ifeq ($(CONFIG_CB710_DEBUG),y)
        CFLAGS-cb710-mmc        += -DDEBUG
 endif
similarity index 58%
rename from drivers/mmc/host/sdhci-of.c
rename to drivers/mmc/host/sdhci-of-core.c
index 01ab916..55e3313 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/mmc/host.h>
 #include <asm/machdep.h>
+#include "sdhci-of.h"
 #include "sdhci.h"
 
-struct sdhci_of_data {
-       unsigned int quirks;
-       struct sdhci_ops ops;
-};
-
-struct sdhci_of_host {
-       unsigned int clock;
-       u16 xfer_mode_shadow;
-};
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 
 /*
- * Ops and quirks for the Freescale eSDHC controller.
+ * These accessors are designed for big endian hosts doing I/O to
+ * little endian controllers incorporating a 32-bit hardware byte swapper.
  */
 
-#define ESDHC_DMA_SYSCTL       0x40c
-#define ESDHC_DMA_SNOOP                0x00000040
-
-#define ESDHC_SYSTEM_CONTROL   0x2c
-#define ESDHC_CLOCK_MASK       0x0000fff0
-#define ESDHC_PREDIV_SHIFT     8
-#define ESDHC_DIVIDER_SHIFT    4
-#define ESDHC_CLOCK_PEREN      0x00000004
-#define ESDHC_CLOCK_HCKEN      0x00000002
-#define ESDHC_CLOCK_IPGEN      0x00000001
-
-#define ESDHC_HOST_CONTROL_RES 0x05
-
-static u32 esdhc_readl(struct sdhci_host *host, int reg)
+u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
 {
        return in_be32(host->ioaddr + reg);
 }
 
-static u16 esdhc_readw(struct sdhci_host *host, int reg)
+u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
 {
-       u16 ret;
-
-       if (unlikely(reg == SDHCI_HOST_VERSION))
-               ret = in_be16(host->ioaddr + reg);
-       else
-               ret = in_be16(host->ioaddr + (reg ^ 0x2));
-       return ret;
+       return in_be16(host->ioaddr + (reg ^ 0x2));
 }
 
-static u8 esdhc_readb(struct sdhci_host *host, int reg)
+u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
 {
        return in_8(host->ioaddr + (reg ^ 0x3));
 }
 
-static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
 {
        out_be32(host->ioaddr + reg, val);
 }
 
-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
+void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
 {
        struct sdhci_of_host *of_host = sdhci_priv(host);
        int base = reg & ~0x3;
@@ -92,106 +67,21 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
                of_host->xfer_mode_shadow = val;
                return;
        case SDHCI_COMMAND:
-               esdhc_writel(host, val << 16 | of_host->xfer_mode_shadow,
-                            SDHCI_TRANSFER_MODE);
+               sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow,
+                                   SDHCI_TRANSFER_MODE);
                return;
-       case SDHCI_BLOCK_SIZE:
-               /*
-                * Two last DMA bits are reserved, and first one is used for
-                * non-standard blksz of 4096 bytes that we don't support
-                * yet. So clear the DMA boundary bits.
-                */
-               val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
-               /* fall through */
        }
        clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
 }
 
-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
 {
        int base = reg & ~0x3;
        int shift = (reg & 0x3) * 8;
 
-       /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
-       if (reg == SDHCI_HOST_CONTROL)
-               val &= ~ESDHC_HOST_CONTROL_RES;
-
        clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
 }
-
-static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
-{
-       int pre_div = 2;
-       int div = 1;
-
-       clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
-                 ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
-
-       if (clock == 0)
-               goto out;
-
-       while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
-               pre_div *= 2;
-
-       while (host->max_clk / pre_div / div > clock && div < 16)
-               div++;
-
-       dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
-               clock, host->max_clk / pre_div / div);
-
-       pre_div >>= 1;
-       div--;
-
-       setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
-                 ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
-                 div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT);
-       mdelay(100);
-out:
-       host->clock = clock;
-}
-
-static int esdhc_enable_dma(struct sdhci_host *host)
-{
-       setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
-       return 0;
-}
-
-static unsigned int esdhc_get_max_clock(struct sdhci_host *host)
-{
-       struct sdhci_of_host *of_host = sdhci_priv(host);
-
-       return of_host->clock;
-}
-
-static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
-{
-       struct sdhci_of_host *of_host = sdhci_priv(host);
-
-       return of_host->clock / 256 / 16;
-}
-
-static struct sdhci_of_data sdhci_esdhc = {
-       .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
-                 SDHCI_QUIRK_BROKEN_CARD_DETECTION |
-                 SDHCI_QUIRK_NO_BUSY_IRQ |
-                 SDHCI_QUIRK_NONSTANDARD_CLOCK |
-                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
-                 SDHCI_QUIRK_PIO_NEEDS_DELAY |
-                 SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
-                 SDHCI_QUIRK_NO_CARD_NO_RESET,
-       .ops = {
-               .readl = esdhc_readl,
-               .readw = esdhc_readw,
-               .readb = esdhc_readb,
-               .writel = esdhc_writel,
-               .writew = esdhc_writew,
-               .writeb = esdhc_writeb,
-               .set_clock = esdhc_set_clock,
-               .enable_dma = esdhc_enable_dma,
-               .get_max_clock = esdhc_get_max_clock,
-               .get_min_clock = esdhc_get_min_clock,
-       },
-};
+#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
 
 #ifdef CONFIG_PM
 
@@ -301,9 +191,14 @@ static int __devexit sdhci_of_remove(struct of_device *ofdev)
 }
 
 static const struct of_device_id sdhci_of_match[] = {
+#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
        { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
        { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
        { .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
+#endif
+#ifdef CONFIG_MMC_SDHCI_OF_HLWD
+       { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, },
+#endif
        { .compatible = "generic-sdhci", },
        {},
 };
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
new file mode 100644 (file)
index 0000000..d5b11a1
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Freescale eSDHC controller driver.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *         Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mmc/host.h>
+#include "sdhci-of.h"
+#include "sdhci.h"
+
+/*
+ * Ops and quirks for the Freescale eSDHC controller.
+ */
+
+#define ESDHC_DMA_SYSCTL       0x40c
+#define ESDHC_DMA_SNOOP                0x00000040
+
+#define ESDHC_SYSTEM_CONTROL   0x2c
+#define ESDHC_CLOCK_MASK       0x0000fff0
+#define ESDHC_PREDIV_SHIFT     8
+#define ESDHC_DIVIDER_SHIFT    4
+#define ESDHC_CLOCK_PEREN      0x00000004
+#define ESDHC_CLOCK_HCKEN      0x00000002
+#define ESDHC_CLOCK_IPGEN      0x00000001
+
+#define ESDHC_HOST_CONTROL_RES 0x05
+
+static u16 esdhc_readw(struct sdhci_host *host, int reg)
+{
+       u16 ret;
+
+       if (unlikely(reg == SDHCI_HOST_VERSION))
+               ret = in_be16(host->ioaddr + reg);
+       else
+               ret = sdhci_be32bs_readw(host, reg);
+       return ret;
+}
+
+static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
+{
+       if (reg == SDHCI_BLOCK_SIZE) {
+               /*
+                * Two last DMA bits are reserved, and first one is used for
+                * non-standard blksz of 4096 bytes that we don't support
+                * yet. So clear the DMA boundary bits.
+                */
+               val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
+       }
+       sdhci_be32bs_writew(host, val, reg);
+}
+
+static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+       /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
+       if (reg == SDHCI_HOST_CONTROL)
+               val &= ~ESDHC_HOST_CONTROL_RES;
+       sdhci_be32bs_writeb(host, val, reg);
+}
+
+static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+       int pre_div = 2;
+       int div = 1;
+
+       clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
+                 ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
+
+       if (clock == 0)
+               goto out;
+
+       while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
+               pre_div *= 2;
+
+       while (host->max_clk / pre_div / div > clock && div < 16)
+               div++;
+
+       dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+               clock, host->max_clk / pre_div / div);
+
+       pre_div >>= 1;
+       div--;
+
+       setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
+                 ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
+                 div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT);
+       mdelay(100);
+out:
+       host->clock = clock;
+}
+
+static int esdhc_enable_dma(struct sdhci_host *host)
+{
+       setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
+       return 0;
+}
+
+static unsigned int esdhc_get_max_clock(struct sdhci_host *host)
+{
+       struct sdhci_of_host *of_host = sdhci_priv(host);
+
+       return of_host->clock;
+}
+
+static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
+{
+       struct sdhci_of_host *of_host = sdhci_priv(host);
+
+       return of_host->clock / 256 / 16;
+}
+
+struct sdhci_of_data sdhci_esdhc = {
+       .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
+                 SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+                 SDHCI_QUIRK_NO_BUSY_IRQ |
+                 SDHCI_QUIRK_NONSTANDARD_CLOCK |
+                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+                 SDHCI_QUIRK_PIO_NEEDS_DELAY |
+                 SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
+                 SDHCI_QUIRK_NO_CARD_NO_RESET,
+       .ops = {
+               .readl = sdhci_be32bs_readl,
+               .readw = esdhc_readw,
+               .readb = sdhci_be32bs_readb,
+               .writel = sdhci_be32bs_writel,
+               .writew = esdhc_writew,
+               .writeb = esdhc_writeb,
+               .set_clock = esdhc_set_clock,
+               .enable_dma = esdhc_enable_dma,
+               .get_max_clock = esdhc_get_max_clock,
+               .get_min_clock = esdhc_get_min_clock,
+       },
+};
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
new file mode 100644 (file)
index 0000000..35117f3
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * drivers/mmc/host/sdhci-of-hlwd.c
+ *
+ * Nintendo Wii Secure Digital Host Controller Interface.
+ * Copyright (C) 2009 The GameCube Linux Team
+ * Copyright (C) 2009 Albert Herranz
+ *
+ * Based on sdhci-of-esdhc.c
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *         Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/mmc/host.h>
+#include "sdhci-of.h"
+#include "sdhci.h"
+
+/*
+ * Ops and quirks for the Nintendo Wii SDHCI controllers.
+ */
+
+/*
+ * We need a small delay after each write, or things go horribly wrong.
+ */
+#define SDHCI_HLWD_WRITE_DELAY 5 /* usecs */
+
+static void sdhci_hlwd_writel(struct sdhci_host *host, u32 val, int reg)
+{
+       sdhci_be32bs_writel(host, val, reg);
+       udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+static void sdhci_hlwd_writew(struct sdhci_host *host, u16 val, int reg)
+{
+       sdhci_be32bs_writew(host, val, reg);
+       udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+       sdhci_be32bs_writeb(host, val, reg);
+       udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+struct sdhci_of_data sdhci_hlwd = {
+       .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
+                 SDHCI_QUIRK_32BIT_DMA_SIZE,
+       .ops = {
+               .readl = sdhci_be32bs_readl,
+               .readw = sdhci_be32bs_readw,
+               .readb = sdhci_be32bs_readb,
+               .writel = sdhci_hlwd_writel,
+               .writew = sdhci_hlwd_writew,
+               .writeb = sdhci_hlwd_writeb,
+       },
+};
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
new file mode 100644 (file)
index 0000000..ad09ad9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * OpenFirmware bindings for Secure Digital Host Controller Interface.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *         Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __SDHCI_OF_H
+#define __SDHCI_OF_H
+
+#include <linux/types.h>
+#include "sdhci.h"
+
+struct sdhci_of_data {
+       unsigned int quirks;
+       struct sdhci_ops ops;
+};
+
+struct sdhci_of_host {
+       unsigned int clock;
+       u16 xfer_mode_shadow;
+};
+
+extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
+extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
+extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
+extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
+extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
+extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
+
+extern struct sdhci_of_data sdhci_esdhc;
+extern struct sdhci_of_data sdhci_hlwd;
+
+#endif /* __SDHCI_OF_H */
index ce5f1d7..842f46f 100644 (file)
@@ -8,6 +8,8 @@
  * the Free Software Foundation; either version 2 of the License, or (at
  * your option) any later version.
  */
+#ifndef __SDHCI_H
+#define __SDHCI_H
 
 #include <linux/scatterlist.h>
 #include <linux/compiler.h>
@@ -408,3 +410,5 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
 extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
 extern int sdhci_resume_host(struct sdhci_host *host);
 #endif
+
+#endif /* __SDHCI_H */
index 74fa075..b13f641 100644 (file)
 
 #include <asm/io.h>
 #include <mach/hardware.h>
-#include <asm/cacheflush.h>
 
 #include <asm/mach/flash.h>
 
+#define CACHELINESIZE  32
+
 static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
                                      ssize_t len)
 {
-       flush_ioremap_region(map->phys, map->cached, from, len);
+       unsigned long start = (unsigned long)map->cached + from;
+       unsigned long end = start + len;
+
+       start &= ~(CACHELINESIZE - 1);
+       while (start < end) {
+               /* invalidate D cache line */
+               asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start));
+               start += CACHELINESIZE;
+       }
 }
 
 struct pxa2xx_flash_info {
index 7678538..677cd53 100644 (file)
@@ -291,14 +291,6 @@ config MTD_NAND_SHARPSL
        tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
        depends on ARCH_PXA
 
-config MTD_NAND_BASLER_EXCITE
-       tristate  "Support for NAND Flash on Basler eXcite"
-       depends on BASLER_EXCITE
-       help
-          This enables the driver for the NAND flash device found on the
-          Basler eXcite Smart Camera. If built as a module, the driver
-          will be named excite_nandflash.
-
 config MTD_NAND_CAFE
        tristate "NAND support for OLPC CAFÉ chip"
        depends on PCI
index 460a1f3..1407bd1 100644 (file)
@@ -27,7 +27,6 @@ obj-$(CONFIG_MTD_NAND_ATMEL)          += atmel_nand.o
 obj-$(CONFIG_MTD_NAND_GPIO)            += gpio.o
 obj-$(CONFIG_MTD_NAND_OMAP2)           += omap2.o
 obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
-obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PXA3xx)          += pxa3xx_nand.o
 obj-$(CONFIG_MTD_NAND_TMIO)            += tmio_nand.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)                += plat_nand.o
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
deleted file mode 100644 (file)
index af6a6a5..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-*  Copyright (C) 2005 - 2007 by Basler Vision Technologies AG
-*  Author: Thomas Koeller <thomas.koeller.qbaslerweb.com>
-*  Original code by Thies Moeller <thies.moeller@baslerweb.com>
-*
-*  This program is free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  This program is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  You should have received a copy of the GNU General Public License
-*  along with this program; if not, write to the Free Software
-*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite_nandflash.h>
-
-#define EXCITE_NANDFLASH_VERSION "0.1"
-
-/* I/O register offsets */
-#define EXCITE_NANDFLASH_DATA_BYTE   0x00
-#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c
-#define EXCITE_NANDFLASH_ADDR_BYTE   0x10
-#define EXCITE_NANDFLASH_CMD_BYTE    0x14
-
-/* prefix for debug output */
-static const char module_id[] = "excite_nandflash";
-
-/*
- * partition definition
- */
-static const struct mtd_partition partition_info[] = {
-       {
-               .name = "eXcite RootFS",
-               .offset = 0,
-               .size = MTDPART_SIZ_FULL
-       }
-};
-
-static inline const struct resource *
-excite_nand_get_resource(struct platform_device *d, unsigned long flags,
-                        const char *basename)
-{
-       char buf[80];
-
-       if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf)
-               return NULL;
-       return platform_get_resource_byname(d, flags, buf);
-}
-
-static inline void __iomem *
-excite_nand_map_regs(struct platform_device *d, const char *basename)
-{
-       void *result = NULL;
-       const struct resource *const r =
-           excite_nand_get_resource(d, IORESOURCE_MEM, basename);
-
-       if (r)
-               result = ioremap_nocache(r->start, r->end + 1 - r->start);
-       return result;
-}
-
-/* controller and mtd information */
-struct excite_nand_drvdata {
-       struct mtd_info board_mtd;
-       struct nand_chip board_chip;
-       void __iomem *regs;
-       void __iomem *tgt;
-};
-
-/* Control function */
-static void excite_nand_control(struct mtd_info *mtd, int cmd,
-                                      unsigned int ctrl)
-{
-       struct excite_nand_drvdata * const d =
-           container_of(mtd, struct excite_nand_drvdata, board_mtd);
-
-       switch (ctrl) {
-       case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
-               d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE;
-               break;
-       case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
-               d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE;
-               break;
-       case NAND_CTRL_CHANGE | NAND_NCE:
-               d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE;
-               break;
-       }
-
-       if (cmd != NAND_CMD_NONE)
-               __raw_writeb(cmd, d->tgt);
-}
-
-/* Return 0 if flash is busy, 1 if ready */
-static int excite_nand_devready(struct mtd_info *mtd)
-{
-       struct excite_nand_drvdata * const drvdata =
-           container_of(mtd, struct excite_nand_drvdata, board_mtd);
-
-       return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE);
-}
-
-/*
- * Called by device layer to remove the driver.
- * The binding to the mtd and all allocated
- * resources are released.
- */
-static int __devexit excite_nand_remove(struct platform_device *dev)
-{
-       struct excite_nand_drvdata * const this = platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
-
-       if (unlikely(!this)) {
-               printk(KERN_ERR "%s: called %s without private data!!",
-                      module_id, __func__);
-               return -EINVAL;
-       }
-
-       /* first thing we need to do is release our mtd
-        * then go through freeing the resource used
-        */
-       nand_release(&this->board_mtd);
-
-       /* free the common resources */
-       iounmap(this->regs);
-       kfree(this);
-
-       DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id);
-       return 0;
-}
-
-/*
- * Called by device layer when it finds a device matching
- * one our driver can handle. This code checks to see if
- * it can allocate all necessary resources then calls the
- * nand layer to look for devices.
-*/
-static int __init excite_nand_probe(struct platform_device *pdev)
-{
-       struct excite_nand_drvdata *drvdata;    /* private driver data */
-       struct nand_chip *board_chip;   /* private flash chip data */
-       struct mtd_info *board_mtd;     /* mtd info for this board */
-       int scan_res;
-
-       drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-       if (unlikely(!drvdata)) {
-               printk(KERN_ERR "%s: no memory for drvdata\n",
-                      module_id);
-               return -ENOMEM;
-       }
-
-       /* bind private data into driver */
-       platform_set_drvdata(pdev, drvdata);
-
-       /* allocate and map the resource */
-       drvdata->regs =
-               excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
-
-       if (unlikely(!drvdata->regs)) {
-               printk(KERN_ERR "%s: cannot reserve register region\n",
-                      module_id);
-               kfree(drvdata);
-               return -ENXIO;
-       }
-       
-       drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
-
-       /* initialise our chip */
-       board_chip = &drvdata->board_chip;
-       board_chip->IO_ADDR_R = board_chip->IO_ADDR_W =
-               drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
-       board_chip->cmd_ctrl = excite_nand_control;
-       board_chip->dev_ready = excite_nand_devready;
-       board_chip->chip_delay = 25;
-       board_chip->ecc.mode = NAND_ECC_SOFT;
-
-       /* link chip to mtd */
-       board_mtd = &drvdata->board_mtd;
-       board_mtd->priv = board_chip;
-
-       DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id);
-       scan_res = nand_scan(&drvdata->board_mtd, 1);
-
-       if (likely(!scan_res)) {
-               DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
-               add_mtd_partitions(&drvdata->board_mtd, partition_info,
-                                  ARRAY_SIZE(partition_info));
-       } else {
-               iounmap(drvdata->regs);
-               kfree(drvdata);
-               printk(KERN_ERR "%s: device scan failed\n", module_id);
-               return -EIO;
-       }
-       return 0;
-}
-
-static struct platform_driver excite_nand_driver = {
-       .driver = {
-               .name = "excite_nand",
-               .owner          = THIS_MODULE,
-       },
-       .probe = excite_nand_probe,
-       .remove = __devexit_p(excite_nand_remove)
-};
-
-static int __init excite_nand_init(void)
-{
-       pr_info("Basler eXcite nand flash driver Version "
-               EXCITE_NANDFLASH_VERSION "\n");
-       return platform_driver_register(&excite_nand_driver);
-}
-
-static void __exit excite_nand_exit(void)
-{
-       platform_driver_unregister(&excite_nand_driver);
-}
-
-module_init(excite_nand_init);
-module_exit(excite_nand_exit);
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(EXCITE_NANDFLASH_VERSION)
index a5be9ac..e58a653 100644 (file)
@@ -1953,6 +1953,8 @@ config BCM63XX_ENET
 
 source "drivers/net/fs_enet/Kconfig"
 
+source "drivers/net/octeon/Kconfig"
+
 endif # NET_ETHERNET
 
 #
index 246323d..ad1346d 100644 (file)
@@ -285,3 +285,5 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
 obj-$(CONFIG_SFC) += sfc/
 
 obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
diff --git a/drivers/net/octeon/Kconfig b/drivers/net/octeon/Kconfig
new file mode 100644 (file)
index 0000000..1e56bbf
--- /dev/null
@@ -0,0 +1,10 @@
+config OCTEON_MGMT_ETHERNET
+       tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)"
+       depends on  CPU_CAVIUM_OCTEON
+       select PHYLIB
+       select MDIO_OCTEON
+       default y
+       help
+         This option enables the ethernet driver for the management
+         port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
+         CN54XX, CN52XX, and CN6XXX chips.
diff --git a/drivers/net/octeon/Makefile b/drivers/net/octeon/Makefile
new file mode 100644 (file)
index 0000000..906edec
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET)     += octeon_mgmt.o
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
new file mode 100644 (file)
index 0000000..050538b
--- /dev/null
@@ -0,0 +1,1176 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Cavium Networks
+ */
+
+#include <linux/capability.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include <linux/spinlock.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-mixx-defs.h>
+#include <asm/octeon/cvmx-agl-defs.h>
+
+#define DRV_NAME "octeon_mgmt"
+#define DRV_VERSION "2.0"
+#define DRV_DESCRIPTION \
+       "Cavium Networks Octeon MII (management) port Network Driver"
+
+#define OCTEON_MGMT_NAPI_WEIGHT 16
+
+/*
+ * Ring sizes that are powers of two allow for more efficient modulo
+ * opertions.
+ */
+#define OCTEON_MGMT_RX_RING_SIZE 512
+#define OCTEON_MGMT_TX_RING_SIZE 128
+
+/* Allow 8 bytes for vlan and FCS. */
+#define OCTEON_MGMT_RX_HEADROOM (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
+
+union mgmt_port_ring_entry {
+       u64 d64;
+       struct {
+               u64    reserved_62_63:2;
+               /* Length of the buffer/packet in bytes */
+               u64    len:14;
+               /* For TX, signals that the packet should be timestamped */
+               u64    tstamp:1;
+               /* The RX error code */
+               u64    code:7;
+#define RING_ENTRY_CODE_DONE 0xf
+#define RING_ENTRY_CODE_MORE 0x10
+               /* Physical address of the buffer */
+               u64    addr:40;
+       } s;
+};
+
+struct octeon_mgmt {
+       struct net_device *netdev;
+       int port;
+       int irq;
+       u64 *tx_ring;
+       dma_addr_t tx_ring_handle;
+       unsigned int tx_next;
+       unsigned int tx_next_clean;
+       unsigned int tx_current_fill;
+       /* The tx_list lock also protects the ring related variables */
+       struct sk_buff_head tx_list;
+
+       /* RX variables only touched in napi_poll.  No locking necessary. */
+       u64 *rx_ring;
+       dma_addr_t rx_ring_handle;
+       unsigned int rx_next;
+       unsigned int rx_next_fill;
+       unsigned int rx_current_fill;
+       struct sk_buff_head rx_list;
+
+       spinlock_t lock;
+       unsigned int last_duplex;
+       unsigned int last_link;
+       struct device *dev;
+       struct napi_struct napi;
+       struct tasklet_struct tx_clean_tasklet;
+       struct phy_device *phydev;
+};
+
+static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
+{
+       int port = p->port;
+       union cvmx_mixx_intena mix_intena;
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->lock, flags);
+       mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+       mix_intena.s.ithena = enable ? 1 : 0;
+       cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+       spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
+{
+       int port = p->port;
+       union cvmx_mixx_intena mix_intena;
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->lock, flags);
+       mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+       mix_intena.s.othena = enable ? 1 : 0;
+       cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+       spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static inline void octeon_mgmt_enable_rx_irq(struct octeon_mgmt *p)
+{
+       octeon_mgmt_set_rx_irq(p, 1);
+}
+
+static inline void octeon_mgmt_disable_rx_irq(struct octeon_mgmt *p)
+{
+       octeon_mgmt_set_rx_irq(p, 0);
+}
+
+static inline void octeon_mgmt_enable_tx_irq(struct octeon_mgmt *p)
+{
+       octeon_mgmt_set_tx_irq(p, 1);
+}
+
+static inline void octeon_mgmt_disable_tx_irq(struct octeon_mgmt *p)
+{
+       octeon_mgmt_set_tx_irq(p, 0);
+}
+
+static unsigned int ring_max_fill(unsigned int ring_size)
+{
+       return ring_size - 8;
+}
+
+static unsigned int ring_size_to_bytes(unsigned int ring_size)
+{
+       return ring_size * sizeof(union mgmt_port_ring_entry);
+}
+
+static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+
+       while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
+               unsigned int size;
+               union mgmt_port_ring_entry re;
+               struct sk_buff *skb;
+
+               /* CN56XX pass 1 needs 8 bytes of padding.  */
+               size = netdev->mtu + OCTEON_MGMT_RX_HEADROOM + 8 + NET_IP_ALIGN;
+
+               skb = netdev_alloc_skb(netdev, size);
+               if (!skb)
+                       break;
+               skb_reserve(skb, NET_IP_ALIGN);
+               __skb_queue_tail(&p->rx_list, skb);
+
+               re.d64 = 0;
+               re.s.len = size;
+               re.s.addr = dma_map_single(p->dev, skb->data,
+                                          size,
+                                          DMA_FROM_DEVICE);
+
+               /* Put it in the ring.  */
+               p->rx_ring[p->rx_next_fill] = re.d64;
+               dma_sync_single_for_device(p->dev, p->rx_ring_handle,
+                                          ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                                          DMA_BIDIRECTIONAL);
+               p->rx_next_fill =
+                       (p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
+               p->rx_current_fill++;
+               /* Ring the bell.  */
+               cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
+       }
+}
+
+static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
+{
+       int port = p->port;
+       union cvmx_mixx_orcnt mix_orcnt;
+       union mgmt_port_ring_entry re;
+       struct sk_buff *skb;
+       int cleaned = 0;
+       unsigned long flags;
+
+       mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+       while (mix_orcnt.s.orcnt) {
+               dma_sync_single_for_cpu(p->dev, p->tx_ring_handle,
+                                       ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                                       DMA_BIDIRECTIONAL);
+
+               spin_lock_irqsave(&p->tx_list.lock, flags);
+
+               re.d64 = p->tx_ring[p->tx_next_clean];
+               p->tx_next_clean =
+                       (p->tx_next_clean + 1) % OCTEON_MGMT_TX_RING_SIZE;
+               skb = __skb_dequeue(&p->tx_list);
+
+               mix_orcnt.u64 = 0;
+               mix_orcnt.s.orcnt = 1;
+
+               /* Acknowledge to hardware that we have the buffer.  */
+               cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64);
+               p->tx_current_fill--;
+
+               spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+               dma_unmap_single(p->dev, re.s.addr, re.s.len,
+                                DMA_TO_DEVICE);
+               dev_kfree_skb_any(skb);
+               cleaned++;
+
+               mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+       }
+
+       if (cleaned && netif_queue_stopped(p->netdev))
+               netif_wake_queue(p->netdev);
+}
+
+static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
+{
+       struct octeon_mgmt *p = (struct octeon_mgmt *)arg;
+       octeon_mgmt_clean_tx_buffers(p);
+       octeon_mgmt_enable_tx_irq(p);
+}
+
+static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       unsigned long flags;
+       u64 drop, bad;
+
+       /* These reads also clear the count registers.  */
+       drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port));
+       bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port));
+
+       if (drop || bad) {
+               /* Do an atomic update. */
+               spin_lock_irqsave(&p->lock, flags);
+               netdev->stats.rx_errors += bad;
+               netdev->stats.rx_dropped += drop;
+               spin_unlock_irqrestore(&p->lock, flags);
+       }
+}
+
+static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       unsigned long flags;
+
+       union cvmx_agl_gmx_txx_stat0 s0;
+       union cvmx_agl_gmx_txx_stat1 s1;
+
+       /* These reads also clear the count registers.  */
+       s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port));
+       s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port));
+
+       if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
+               /* Do an atomic update. */
+               spin_lock_irqsave(&p->lock, flags);
+               netdev->stats.tx_errors += s0.s.xsdef + s0.s.xscol;
+               netdev->stats.collisions += s1.s.scol + s1.s.mcol;
+               spin_unlock_irqrestore(&p->lock, flags);
+       }
+}
+
+/*
+ * Dequeue a receive skb and its corresponding ring entry.  The ring
+ * entry is returned, *pskb is updated to point to the skb.
+ */
+static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
+                                        struct sk_buff **pskb)
+{
+       union mgmt_port_ring_entry re;
+
+       dma_sync_single_for_cpu(p->dev, p->rx_ring_handle,
+                               ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                               DMA_BIDIRECTIONAL);
+
+       re.d64 = p->rx_ring[p->rx_next];
+       p->rx_next = (p->rx_next + 1) % OCTEON_MGMT_RX_RING_SIZE;
+       p->rx_current_fill--;
+       *pskb = __skb_dequeue(&p->rx_list);
+
+       dma_unmap_single(p->dev, re.s.addr,
+                        ETH_FRAME_LEN + OCTEON_MGMT_RX_HEADROOM,
+                        DMA_FROM_DEVICE);
+
+       return re.d64;
+}
+
+
+static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
+{
+       int port = p->port;
+       struct net_device *netdev = p->netdev;
+       union cvmx_mixx_ircnt mix_ircnt;
+       union mgmt_port_ring_entry re;
+       struct sk_buff *skb;
+       struct sk_buff *skb2;
+       struct sk_buff *skb_new;
+       union mgmt_port_ring_entry re2;
+       int rc = 1;
+
+
+       re.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb);
+       if (likely(re.s.code == RING_ENTRY_CODE_DONE)) {
+               /* A good packet, send it up. */
+               skb_put(skb, re.s.len);
+good:
+               skb->protocol = eth_type_trans(skb, netdev);
+               netdev->stats.rx_packets++;
+               netdev->stats.rx_bytes += skb->len;
+               netdev->last_rx = jiffies;
+               netif_receive_skb(skb);
+               rc = 0;
+       } else if (re.s.code == RING_ENTRY_CODE_MORE) {
+               /*
+                * Packet split across skbs.  This can happen if we
+                * increase the MTU.  Buffers that are already in the
+                * rx ring can then end up being too small.  As the rx
+                * ring is refilled, buffers sized for the new MTU
+                * will be used and we should go back to the normal
+                * non-split case.
+                */
+               skb_put(skb, re.s.len);
+               do {
+                       re2.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb2);
+                       if (re2.s.code != RING_ENTRY_CODE_MORE
+                               && re2.s.code != RING_ENTRY_CODE_DONE)
+                               goto split_error;
+                       skb_put(skb2,  re2.s.len);
+                       skb_new = skb_copy_expand(skb, 0, skb2->len,
+                                                 GFP_ATOMIC);
+                       if (!skb_new)
+                               goto split_error;
+                       if (skb_copy_bits(skb2, 0, skb_tail_pointer(skb_new),
+                                         skb2->len))
+                               goto split_error;
+                       skb_put(skb_new, skb2->len);
+                       dev_kfree_skb_any(skb);
+                       dev_kfree_skb_any(skb2);
+                       skb = skb_new;
+               } while (re2.s.code == RING_ENTRY_CODE_MORE);
+               goto good;
+       } else {
+               /* Some other error, discard it. */
+               dev_kfree_skb_any(skb);
+               /*
+                * Error statistics are accumulated in
+                * octeon_mgmt_update_rx_stats.
+                */
+       }
+       goto done;
+split_error:
+       /* Discard the whole mess. */
+       dev_kfree_skb_any(skb);
+       dev_kfree_skb_any(skb2);
+       while (re2.s.code == RING_ENTRY_CODE_MORE) {
+               re2.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb2);
+               dev_kfree_skb_any(skb2);
+       }
+       netdev->stats.rx_errors++;
+
+done:
+       /* Tell the hardware we processed a packet.  */
+       mix_ircnt.u64 = 0;
+       mix_ircnt.s.ircnt = 1;
+       cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64);
+       return rc;
+
+}
+
+static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
+{
+       int port = p->port;
+       unsigned int work_done = 0;
+       union cvmx_mixx_ircnt mix_ircnt;
+       int rc;
+
+
+       mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+       while (work_done < budget && mix_ircnt.s.ircnt) {
+
+               rc = octeon_mgmt_receive_one(p);
+               if (!rc)
+                       work_done++;
+
+               /* Check for more packets. */
+               mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+       }
+
+       octeon_mgmt_rx_fill_ring(p->netdev);
+
+       return work_done;
+}
+
+static int octeon_mgmt_napi_poll(struct napi_struct *napi, int budget)
+{
+       struct octeon_mgmt *p = container_of(napi, struct octeon_mgmt, napi);
+       struct net_device *netdev = p->netdev;
+       unsigned int work_done = 0;
+
+       work_done = octeon_mgmt_receive_packets(p, budget);
+
+       if (work_done < budget) {
+               /* We stopped because no more packets were available. */
+               napi_complete(napi);
+               octeon_mgmt_enable_rx_irq(p);
+       }
+       octeon_mgmt_update_rx_stats(netdev);
+
+       return work_done;
+}
+
+/* Reset the hardware to clean state.  */
+static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
+{
+       union cvmx_mixx_ctl mix_ctl;
+       union cvmx_mixx_bist mix_bist;
+       union cvmx_agl_gmx_bist agl_gmx_bist;
+
+       mix_ctl.u64 = 0;
+       cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+       do {
+               mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+       } while (mix_ctl.s.busy);
+       mix_ctl.s.reset = 1;
+       cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+       cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+       cvmx_wait(64);
+
+       mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port));
+       if (mix_bist.u64)
+               dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
+                       (unsigned long long)mix_bist.u64);
+
+       agl_gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST);
+       if (agl_gmx_bist.u64)
+               dev_warn(p->dev, "AGL failed BIST (0x%016llx)\n",
+                        (unsigned long long)agl_gmx_bist.u64);
+}
+
+struct octeon_mgmt_cam_state {
+       u64 cam[6];
+       u64 cam_mask;
+       int cam_index;
+};
+
+static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
+                                     unsigned char *addr)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               cs->cam[i] |= (u64)addr[i] << (8 * (cs->cam_index));
+       cs->cam_mask |= (1ULL << cs->cam_index);
+       cs->cam_index++;
+}
+
+static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       int i;
+       union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
+       union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
+       unsigned long flags;
+       unsigned int prev_packet_enable;
+       unsigned int cam_mode = 1; /* 1 - Accept on CAM match */
+       unsigned int multicast_mode = 1; /* 1 - Reject all multicast.  */
+       struct octeon_mgmt_cam_state cam_state;
+       struct dev_addr_list *list;
+       struct list_head *pos;
+       int available_cam_entries;
+
+       memset(&cam_state, 0, sizeof(cam_state));
+
+       if ((netdev->flags & IFF_PROMISC) || netdev->dev_addrs.count > 7) {
+               cam_mode = 0;
+               available_cam_entries = 8;
+       } else {
+               /*
+                * One CAM entry for the primary address, leaves seven
+                * for the secondary addresses.
+                */
+               available_cam_entries = 7 - netdev->dev_addrs.count;
+       }
+
+       if (netdev->flags & IFF_MULTICAST) {
+               if (cam_mode == 0 || (netdev->flags & IFF_ALLMULTI)
+                   || netdev->mc_count  > available_cam_entries)
+                       multicast_mode = 2; /* 1 - Accept all multicast.  */
+               else
+                       multicast_mode = 0; /* 0 - Use CAM.  */
+       }
+
+       if (cam_mode == 1) {
+               /* Add primary address. */
+               octeon_mgmt_cam_state_add(&cam_state, netdev->dev_addr);
+               list_for_each(pos, &netdev->dev_addrs.list) {
+                       struct netdev_hw_addr *hw_addr;
+                       hw_addr = list_entry(pos, struct netdev_hw_addr, list);
+                       octeon_mgmt_cam_state_add(&cam_state, hw_addr->addr);
+                       list = list->next;
+               }
+       }
+       if (multicast_mode == 0) {
+               i = netdev->mc_count;
+               list = netdev->mc_list;
+               while (i--) {
+                       octeon_mgmt_cam_state_add(&cam_state, list->da_addr);
+                       list = list->next;
+               }
+       }
+
+
+       spin_lock_irqsave(&p->lock, flags);
+
+       /* Disable packet I/O. */
+       agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+       prev_packet_enable = agl_gmx_prtx.s.en;
+       agl_gmx_prtx.s.en = 0;
+       cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+
+
+       adr_ctl.u64 = 0;
+       adr_ctl.s.cam_mode = cam_mode;
+       adr_ctl.s.mcst = multicast_mode;
+       adr_ctl.s.bcst = 1;     /* Allow broadcast */
+
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64);
+
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask);
+
+       /* Restore packet I/O. */
+       agl_gmx_prtx.s.en = prev_packet_enable;
+       cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+
+       spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
+{
+       struct sockaddr *sa = addr;
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(netdev->dev_addr, sa->sa_data, ETH_ALEN);
+
+       octeon_mgmt_set_rx_filtering(netdev);
+
+       return 0;
+}
+
+static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
+
+       /*
+        * Limit the MTU to make sure the ethernet packets are between
+        * 64 bytes and 16383 bytes.
+        */
+       if (size_without_fcs < 64 || size_without_fcs > 16383) {
+               dev_warn(p->dev, "MTU must be between %d and %d.\n",
+                        64 - OCTEON_MGMT_RX_HEADROOM,
+                        16383 - OCTEON_MGMT_RX_HEADROOM);
+               return -EINVAL;
+       }
+
+       netdev->mtu = new_mtu;
+
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
+                      (size_without_fcs + 7) & 0xfff8);
+
+       return 0;
+}
+
+static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
+{
+       struct net_device *netdev = dev_id;
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       union cvmx_mixx_isr mixx_isr;
+
+       mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port));
+
+       /* Clear any pending interrupts */
+       cvmx_write_csr(CVMX_MIXX_ISR(port),
+                      cvmx_read_csr(CVMX_MIXX_ISR(port)));
+       cvmx_read_csr(CVMX_MIXX_ISR(port));
+
+       if (mixx_isr.s.irthresh) {
+               octeon_mgmt_disable_rx_irq(p);
+               napi_schedule(&p->napi);
+       }
+       if (mixx_isr.s.orthresh) {
+               octeon_mgmt_disable_tx_irq(p);
+               tasklet_schedule(&p->tx_clean_tasklet);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int octeon_mgmt_ioctl(struct net_device *netdev,
+                            struct ifreq *rq, int cmd)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+
+       if (!netif_running(netdev))
+               return -EINVAL;
+
+       if (!p->phydev)
+               return -EINVAL;
+
+       return phy_mii_ioctl(p->phydev, if_mii(rq), cmd);
+}
+
+static void octeon_mgmt_adjust_link(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+       unsigned long flags;
+       int link_changed = 0;
+
+       spin_lock_irqsave(&p->lock, flags);
+       if (p->phydev->link) {
+               if (!p->last_link)
+                       link_changed = 1;
+               if (p->last_duplex != p->phydev->duplex) {
+                       p->last_duplex = p->phydev->duplex;
+                       prtx_cfg.u64 =
+                               cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+                       prtx_cfg.s.duplex = p->phydev->duplex;
+                       cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
+                                      prtx_cfg.u64);
+               }
+       } else {
+               if (p->last_link)
+                       link_changed = -1;
+       }
+       p->last_link = p->phydev->link;
+       spin_unlock_irqrestore(&p->lock, flags);
+
+       if (link_changed != 0) {
+               if (link_changed > 0) {
+                       netif_carrier_on(netdev);
+                       pr_info("%s: Link is up - %d/%s\n", netdev->name,
+                               p->phydev->speed,
+                               DUPLEX_FULL == p->phydev->duplex ?
+                               "Full" : "Half");
+               } else {
+                       netif_carrier_off(netdev);
+                       pr_info("%s: Link is down\n", netdev->name);
+               }
+       }
+}
+
+static int octeon_mgmt_init_phy(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       char phy_id[20];
+
+       if (octeon_is_simulation()) {
+               /* No PHYs in the simulator. */
+               netif_carrier_on(netdev);
+               return 0;
+       }
+
+       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
+
+       p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
+                               PHY_INTERFACE_MODE_MII);
+
+       if (IS_ERR(p->phydev)) {
+               p->phydev = NULL;
+               return -1;
+       }
+
+       phy_start_aneg(p->phydev);
+
+       return 0;
+}
+
+static int octeon_mgmt_open(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       union cvmx_mixx_ctl mix_ctl;
+       union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode;
+       union cvmx_mixx_oring1 oring1;
+       union cvmx_mixx_iring1 iring1;
+       union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+       union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl;
+       union cvmx_mixx_irhwm mix_irhwm;
+       union cvmx_mixx_orhwm mix_orhwm;
+       union cvmx_mixx_intena mix_intena;
+       struct sockaddr sa;
+
+       /* Allocate ring buffers.  */
+       p->tx_ring = kzalloc(ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                            GFP_KERNEL);
+       if (!p->tx_ring)
+               return -ENOMEM;
+       p->tx_ring_handle =
+               dma_map_single(p->dev, p->tx_ring,
+                              ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                              DMA_BIDIRECTIONAL);
+       p->tx_next = 0;
+       p->tx_next_clean = 0;
+       p->tx_current_fill = 0;
+
+
+       p->rx_ring = kzalloc(ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                            GFP_KERNEL);
+       if (!p->rx_ring)
+               goto err_nomem;
+       p->rx_ring_handle =
+               dma_map_single(p->dev, p->rx_ring,
+                              ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                              DMA_BIDIRECTIONAL);
+
+       p->rx_next = 0;
+       p->rx_next_fill = 0;
+       p->rx_current_fill = 0;
+
+       octeon_mgmt_reset_hw(p);
+
+       mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+
+       /* Bring it out of reset if needed. */
+       if (mix_ctl.s.reset) {
+               mix_ctl.s.reset = 0;
+               cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+               do {
+                       mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+               } while (mix_ctl.s.reset);
+       }
+
+       agl_gmx_inf_mode.u64 = 0;
+       agl_gmx_inf_mode.s.en = 1;
+       cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+
+       oring1.u64 = 0;
+       oring1.s.obase = p->tx_ring_handle >> 3;
+       oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
+       cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
+
+       iring1.u64 = 0;
+       iring1.s.ibase = p->rx_ring_handle >> 3;
+       iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
+       cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
+
+       /* Disable packet I/O. */
+       prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+       prtx_cfg.s.en = 0;
+       cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+
+       memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
+       octeon_mgmt_set_mac_address(netdev, &sa);
+
+       octeon_mgmt_change_mtu(netdev, netdev->mtu);
+
+       /*
+        * Enable the port HW. Packets are not allowed until
+        * cvmx_mgmt_port_enable() is called.
+        */
+       mix_ctl.u64 = 0;
+       mix_ctl.s.crc_strip = 1;    /* Strip the ending CRC */
+       mix_ctl.s.en = 1;           /* Enable the port */
+       mix_ctl.s.nbtarb = 0;       /* Arbitration mode */
+       /* MII CB-request FIFO programmable high watermark */
+       mix_ctl.s.mrq_hwm = 1;
+       cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+
+       if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+           || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+               /*
+                * Force compensation values, as they are not
+                * determined properly by HW
+                */
+               union cvmx_agl_gmx_drv_ctl drv_ctl;
+
+               drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL);
+               if (port) {
+                       drv_ctl.s.byp_en1 = 1;
+                       drv_ctl.s.nctl1 = 6;
+                       drv_ctl.s.pctl1 = 6;
+               } else {
+                       drv_ctl.s.byp_en = 1;
+                       drv_ctl.s.nctl = 6;
+                       drv_ctl.s.pctl = 6;
+               }
+               cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64);
+       }
+
+       octeon_mgmt_rx_fill_ring(netdev);
+
+       /* Clear statistics. */
+       /* Clear on read. */
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0);
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0);
+
+       cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1);
+       cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0);
+       cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0);
+
+       /* Clear any pending interrupts */
+       cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port)));
+
+       if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
+                       netdev)) {
+               dev_err(p->dev, "request_irq(%d) failed.\n", p->irq);
+               goto err_noirq;
+       }
+
+       /* Interrupt every single RX packet */
+       mix_irhwm.u64 = 0;
+       mix_irhwm.s.irhwm = 0;
+       cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64);
+
+       /* Interrupt when we have 5 or more packets to clean.  */
+       mix_orhwm.u64 = 0;
+       mix_orhwm.s.orhwm = 5;
+       cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64);
+
+       /* Enable receive and transmit interrupts */
+       mix_intena.u64 = 0;
+       mix_intena.s.ithena = 1;
+       mix_intena.s.othena = 1;
+       cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+
+
+       /* Enable packet I/O. */
+
+       rxx_frm_ctl.u64 = 0;
+       rxx_frm_ctl.s.pre_align = 1;
+       /*
+        * When set, disables the length check for non-min sized pkts
+        * with padding in the client data.
+        */
+       rxx_frm_ctl.s.pad_len = 1;
+       /* When set, disables the length check for VLAN pkts */
+       rxx_frm_ctl.s.vlan_len = 1;
+       /* When set, PREAMBLE checking is  less strict */
+       rxx_frm_ctl.s.pre_free = 1;
+       /* Control Pause Frames can match station SMAC */
+       rxx_frm_ctl.s.ctl_smac = 0;
+       /* Control Pause Frames can match globally assign Multicast address */
+       rxx_frm_ctl.s.ctl_mcst = 1;
+       /* Forward pause information to TX block */
+       rxx_frm_ctl.s.ctl_bck = 1;
+       /* Drop Control Pause Frames */
+       rxx_frm_ctl.s.ctl_drp = 1;
+       /* Strip off the preamble */
+       rxx_frm_ctl.s.pre_strp = 1;
+       /*
+        * This port is configured to send PREAMBLE+SFD to begin every
+        * frame.  GMX checks that the PREAMBLE is sent correctly.
+        */
+       rxx_frm_ctl.s.pre_chk = 1;
+       cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
+
+       /* Enable the AGL block */
+       agl_gmx_inf_mode.u64 = 0;
+       agl_gmx_inf_mode.s.en = 1;
+       cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+
+       /* Configure the port duplex and enables */
+       prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+       prtx_cfg.s.tx_en = 1;
+       prtx_cfg.s.rx_en = 1;
+       prtx_cfg.s.en = 1;
+       p->last_duplex = 1;
+       prtx_cfg.s.duplex = p->last_duplex;
+       cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+
+       p->last_link = 0;
+       netif_carrier_off(netdev);
+
+       if (octeon_mgmt_init_phy(netdev)) {
+               dev_err(p->dev, "Cannot initialize PHY.\n");
+               goto err_noirq;
+       }
+
+       netif_wake_queue(netdev);
+       napi_enable(&p->napi);
+
+       return 0;
+err_noirq:
+       octeon_mgmt_reset_hw(p);
+       dma_unmap_single(p->dev, p->rx_ring_handle,
+                        ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                        DMA_BIDIRECTIONAL);
+       kfree(p->rx_ring);
+err_nomem:
+       dma_unmap_single(p->dev, p->tx_ring_handle,
+                        ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                        DMA_BIDIRECTIONAL);
+       kfree(p->tx_ring);
+       return -ENOMEM;
+}
+
+static int octeon_mgmt_stop(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+
+       napi_disable(&p->napi);
+       netif_stop_queue(netdev);
+
+       if (p->phydev)
+               phy_disconnect(p->phydev);
+
+       netif_carrier_off(netdev);
+
+       octeon_mgmt_reset_hw(p);
+
+
+       free_irq(p->irq, netdev);
+
+       /* dma_unmap is a nop on Octeon, so just free everything.  */
+       skb_queue_purge(&p->tx_list);
+       skb_queue_purge(&p->rx_list);
+
+       dma_unmap_single(p->dev, p->rx_ring_handle,
+                        ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+                        DMA_BIDIRECTIONAL);
+       kfree(p->rx_ring);
+
+       dma_unmap_single(p->dev, p->tx_ring_handle,
+                        ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                        DMA_BIDIRECTIONAL);
+       kfree(p->tx_ring);
+
+
+       return 0;
+}
+
+static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+       int port = p->port;
+       union mgmt_port_ring_entry re;
+       unsigned long flags;
+
+       re.d64 = 0;
+       re.s.len = skb->len;
+       re.s.addr = dma_map_single(p->dev, skb->data,
+                                  skb->len,
+                                  DMA_TO_DEVICE);
+
+       spin_lock_irqsave(&p->tx_list.lock, flags);
+
+       if (unlikely(p->tx_current_fill >=
+                    ring_max_fill(OCTEON_MGMT_TX_RING_SIZE))) {
+               spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+               dma_unmap_single(p->dev, re.s.addr, re.s.len,
+                                DMA_TO_DEVICE);
+
+               netif_stop_queue(netdev);
+               return NETDEV_TX_BUSY;
+       }
+
+       __skb_queue_tail(&p->tx_list, skb);
+
+       /* Put it in the ring.  */
+       p->tx_ring[p->tx_next] = re.d64;
+       p->tx_next = (p->tx_next + 1) % OCTEON_MGMT_TX_RING_SIZE;
+       p->tx_current_fill++;
+
+       spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+       dma_sync_single_for_device(p->dev, p->tx_ring_handle,
+                                  ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+                                  DMA_BIDIRECTIONAL);
+
+       netdev->stats.tx_packets++;
+       netdev->stats.tx_bytes += skb->len;
+
+       /* Ring the bell.  */
+       cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+
+       netdev->trans_start = jiffies;
+       octeon_mgmt_clean_tx_buffers(p);
+       octeon_mgmt_update_tx_stats(netdev);
+       return NETDEV_TX_OK;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void octeon_mgmt_poll_controller(struct net_device *netdev)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+
+       octeon_mgmt_receive_packets(p, 16);
+       octeon_mgmt_update_rx_stats(netdev);
+       return;
+}
+#endif
+
+static void octeon_mgmt_get_drvinfo(struct net_device *netdev,
+                                   struct ethtool_drvinfo *info)
+{
+       strncpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strncpy(info->version, DRV_VERSION, sizeof(info->version));
+       strncpy(info->fw_version, "N/A", sizeof(info->fw_version));
+       strncpy(info->bus_info, "N/A", sizeof(info->bus_info));
+       info->n_stats = 0;
+       info->testinfo_len = 0;
+       info->regdump_len = 0;
+       info->eedump_len = 0;
+}
+
+static int octeon_mgmt_get_settings(struct net_device *netdev,
+                                   struct ethtool_cmd *cmd)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+
+       if (p->phydev)
+               return phy_ethtool_gset(p->phydev, cmd);
+
+       return -EINVAL;
+}
+
+static int octeon_mgmt_set_settings(struct net_device *netdev,
+                                   struct ethtool_cmd *cmd)
+{
+       struct octeon_mgmt *p = netdev_priv(netdev);
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       if (p->phydev)
+               return phy_ethtool_sset(p->phydev, cmd);
+
+       return -EINVAL;
+}
+
+static const struct ethtool_ops octeon_mgmt_ethtool_ops = {
+       .get_drvinfo = octeon_mgmt_get_drvinfo,
+       .get_link = ethtool_op_get_link,
+       .get_settings = octeon_mgmt_get_settings,
+       .set_settings = octeon_mgmt_set_settings
+};
+
+static const struct net_device_ops octeon_mgmt_ops = {
+       .ndo_open =                     octeon_mgmt_open,
+       .ndo_stop =                     octeon_mgmt_stop,
+       .ndo_start_xmit =               octeon_mgmt_xmit,
+       .ndo_set_rx_mode =              octeon_mgmt_set_rx_filtering,
+       .ndo_set_multicast_list =       octeon_mgmt_set_rx_filtering,
+       .ndo_set_mac_address =          octeon_mgmt_set_mac_address,
+       .ndo_do_ioctl =                 octeon_mgmt_ioctl,
+       .ndo_change_mtu =               octeon_mgmt_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller =          octeon_mgmt_poll_controller,
+#endif
+};
+
+static int __init octeon_mgmt_probe(struct platform_device *pdev)
+{
+       struct resource *res_irq;
+       struct net_device *netdev;
+       struct octeon_mgmt *p;
+       int i;
+
+       netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
+       if (netdev == NULL)
+               return -ENOMEM;
+
+       dev_set_drvdata(&pdev->dev, netdev);
+       p = netdev_priv(netdev);
+       netif_napi_add(netdev, &p->napi, octeon_mgmt_napi_poll,
+                      OCTEON_MGMT_NAPI_WEIGHT);
+
+       p->netdev = netdev;
+       p->dev = &pdev->dev;
+
+       p->port = pdev->id;
+       snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
+
+       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res_irq)
+               goto err;
+
+       p->irq = res_irq->start;
+       spin_lock_init(&p->lock);
+
+       skb_queue_head_init(&p->tx_list);
+       skb_queue_head_init(&p->rx_list);
+       tasklet_init(&p->tx_clean_tasklet,
+                    octeon_mgmt_clean_tx_tasklet, (unsigned long)p);
+
+       netdev->netdev_ops = &octeon_mgmt_ops;
+       netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
+
+
+       /* The mgmt ports get the first N MACs.  */
+       for (i = 0; i < 6; i++)
+               netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i];
+       netdev->dev_addr[5] += p->port;
+
+       if (p->port >= octeon_bootinfo->mac_addr_count)
+               dev_err(&pdev->dev,
+                       "Error %s: Using MAC outside of the assigned range: "
+                       "%02x:%02x:%02x:%02x:%02x:%02x\n", netdev->name,
+                       netdev->dev_addr[0], netdev->dev_addr[1],
+                       netdev->dev_addr[2], netdev->dev_addr[3],
+                       netdev->dev_addr[4], netdev->dev_addr[5]);
+
+       if (register_netdev(netdev))
+               goto err;
+
+       dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+       return 0;
+err:
+       free_netdev(netdev);
+       return -ENOENT;
+}
+
+static int __exit octeon_mgmt_remove(struct platform_device *pdev)
+{
+       struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+
+       unregister_netdev(netdev);
+       free_netdev(netdev);
+       return 0;
+}
+
+static struct platform_driver octeon_mgmt_driver = {
+       .driver = {
+               .name           = "octeon_mgmt",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = octeon_mgmt_probe,
+       .remove         = __exit_p(octeon_mgmt_remove),
+};
+
+extern void octeon_mdiobus_force_mod_depencency(void);
+
+static int __init octeon_mgmt_mod_init(void)
+{
+       /* Force our mdiobus driver module to be loaded first. */
+       octeon_mdiobus_force_mod_depencency();
+       return platform_driver_register(&octeon_mgmt_driver);
+}
+
+static void __exit octeon_mgmt_mod_exit(void)
+{
+       platform_driver_unregister(&octeon_mgmt_driver);
+}
+
+module_init(octeon_mgmt_mod_init);
+module_exit(octeon_mgmt_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
index d5d8e1c..fc5938b 100644 (file)
@@ -115,4 +115,15 @@ config MDIO_GPIO
          To compile this driver as a module, choose M here: the module
          will be called mdio-gpio.
 
+config MDIO_OCTEON
+       tristate "Support for MDIO buses on Octeon SOCs"
+       depends on  CPU_CAVIUM_OCTEON
+       default y
+       help
+
+         This module provides a driver for the Octeon MDIO busses.
+         It is required by the Octeon Ethernet device drivers.
+
+         If in doubt, say Y.
+
 endif # PHYLIB
index edfaac4..1342585 100644 (file)
@@ -20,3 +20,4 @@ obj-$(CONFIG_MDIO_BITBANG)    += mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)                += mdio-gpio.o
 obj-$(CONFIG_NATIONAL_PHY)     += national.o
 obj-$(CONFIG_STE10XP)          += ste10Xp.o
+obj-$(CONFIG_MDIO_OCTEON)      += mdio-octeon.o
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
new file mode 100644 (file)
index 0000000..61a4461
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Cavium Networks
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-smix-defs.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
+
+struct octeon_mdiobus {
+       struct mii_bus *mii_bus;
+       int unit;
+       int phy_irq[PHY_MAX_ADDR];
+};
+
+static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+       struct octeon_mdiobus *p = bus->priv;
+       union cvmx_smix_cmd smi_cmd;
+       union cvmx_smix_rd_dat smi_rd;
+       int timeout = 1000;
+
+       smi_cmd.u64 = 0;
+       smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
+       smi_cmd.s.phy_adr = phy_id;
+       smi_cmd.s.reg_adr = regnum;
+       cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+
+       do {
+               /*
+                * Wait 1000 clocks so we don't saturate the RSL bus
+                * doing reads.
+                */
+               cvmx_wait(1000);
+               smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
+       } while (smi_rd.s.pending && --timeout);
+
+       if (smi_rd.s.val)
+               return smi_rd.s.dat;
+       else
+               return -EIO;
+}
+
+static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
+                               int regnum, u16 val)
+{
+       struct octeon_mdiobus *p = bus->priv;
+       union cvmx_smix_cmd smi_cmd;
+       union cvmx_smix_wr_dat smi_wr;
+       int timeout = 1000;
+
+       smi_wr.u64 = 0;
+       smi_wr.s.dat = val;
+       cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
+
+       smi_cmd.u64 = 0;
+       smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
+       smi_cmd.s.phy_adr = phy_id;
+       smi_cmd.s.reg_adr = regnum;
+       cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+
+       do {
+               /*
+                * Wait 1000 clocks so we don't saturate the RSL bus
+                * doing reads.
+                */
+               cvmx_wait(1000);
+               smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
+       } while (smi_wr.s.pending && --timeout);
+
+       if (timeout <= 0)
+               return -EIO;
+
+       return 0;
+}
+
+static int __init octeon_mdiobus_probe(struct platform_device *pdev)
+{
+       struct octeon_mdiobus *bus;
+       int i;
+       int err = -ENOENT;
+
+       bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+       if (!bus)
+               return -ENOMEM;
+
+       /* The platform_device id is our unit number.  */
+       bus->unit = pdev->id;
+
+       bus->mii_bus = mdiobus_alloc();
+
+       if (!bus->mii_bus)
+               goto err;
+
+       /*
+        * Standard Octeon evaluation boards don't support phy
+        * interrupts, we need to poll.
+        */
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               bus->phy_irq[i] = PHY_POLL;
+
+       bus->mii_bus->priv = bus;
+       bus->mii_bus->irq = bus->phy_irq;
+       bus->mii_bus->name = "mdio-octeon";
+       snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
+       bus->mii_bus->parent = &pdev->dev;
+
+       bus->mii_bus->read = octeon_mdiobus_read;
+       bus->mii_bus->write = octeon_mdiobus_write;
+
+       dev_set_drvdata(&pdev->dev, bus);
+
+       err = mdiobus_register(bus->mii_bus);
+       if (err)
+               goto err_register;
+
+       dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+
+       return 0;
+err_register:
+       mdiobus_free(bus->mii_bus);
+
+err:
+       devm_kfree(&pdev->dev, bus);
+       return err;
+}
+
+static int __exit octeon_mdiobus_remove(struct platform_device *pdev)
+{
+       struct octeon_mdiobus *bus;
+
+       bus = dev_get_drvdata(&pdev->dev);
+
+       mdiobus_unregister(bus->mii_bus);
+       mdiobus_free(bus->mii_bus);
+       return 0;
+}
+
+static struct platform_driver octeon_mdiobus_driver = {
+       .driver = {
+               .name           = "mdio-octeon",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = octeon_mdiobus_probe,
+       .remove         = __exit_p(octeon_mdiobus_remove),
+};
+
+void octeon_mdiobus_force_mod_depencency(void)
+{
+       /* Let ethernet drivers force us to be loaded.  */
+}
+EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
+
+static int __init octeon_mdiobus_mod_init(void)
+{
+       return platform_driver_register(&octeon_mdiobus_driver);
+}
+
+static void __exit octeon_mdiobus_mod_exit(void)
+{
+       platform_driver_unregister(&octeon_mdiobus_driver);
+}
+
+module_init(octeon_mdiobus_mod_init);
+module_exit(octeon_mdiobus_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
index 675b7df..27ca859 100644 (file)
@@ -63,7 +63,7 @@
 #ifndef __iwl_core_h__
 #define __iwl_core_h__
 
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 /************************
  * forward declarations *
index 3aabf1e..76e640b 100644 (file)
@@ -291,7 +291,7 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
                skt->nr = ops->first + i;
                skt->ops = ops;
                skt->socket.owner = ops->owner;
-               skt->socket.dev.parent = dev;
+               skt->socket.dev.parent = &dev->dev;
                skt->socket.pci_irq = NO_IRQ;
 
                ret = pxa2xx_drv_pcmcia_add_one(skt);
@@ -304,8 +304,8 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
                        soc_pcmcia_remove_one(&sinfo->skt[i]);
                kfree(sinfo);
        } else {
-               pxa2xx_configure_sockets(dev);
-               dev_set_drvdata(dev, sinfo);
+               pxa2xx_configure_sockets(&dev->dev);
+               dev_set_drvdata(&dev->dev, sinfo);
        }
 
        return ret;
index 11003bb..1a387e7 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
-#include <linux/autoconf.h>
 
 #define COMPAL_DRIVER_VERSION "0.2.6"
 
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
new file mode 100644 (file)
index 0000000..0471955
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * Regulators driver for Marvell 88PM8607
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *     Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/88pm8607.h>
+
+struct pm8607_regulator_info {
+       struct regulator_desc   desc;
+       struct pm8607_chip      *chip;
+       struct regulator_dev    *regulator;
+
+       int     min_uV;
+       int     max_uV;
+       int     step_uV;
+       int     vol_reg;
+       int     vol_shift;
+       int     vol_nbits;
+       int     update_reg;
+       int     update_bit;
+       int     enable_reg;
+       int     enable_bit;
+       int     slope_double;
+};
+
+static inline int check_range(struct pm8607_regulator_info *info,
+                               int min_uV, int max_uV)
+{
+       if (max_uV < info->min_uV || min_uV > info->max_uV || min_uV > max_uV)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       uint8_t chip_id = info->chip->chip_id;
+       int ret = -EINVAL;
+
+       switch (info->desc.id) {
+       case PM8607_ID_BUCK1:
+               ret = (index < 0x1d) ? (index * 25000 + 800000) :
+                       ((index < 0x20) ? 1500000 :
+                       ((index < 0x40) ? ((index - 0x20) * 25000) :
+                       -EINVAL));
+               break;
+       case PM8607_ID_BUCK3:
+               ret = (index < 0x3d) ? (index * 25000) :
+                       ((index < 0x40) ? 1500000 : -EINVAL);
+               if (ret < 0)
+                       break;
+               if (info->slope_double)
+                       ret <<= 1;
+               break;
+       case PM8607_ID_LDO1:
+               ret = (index == 0) ? 1800000 :
+                       ((index == 1) ? 1200000 :
+                       ((index == 2) ? 2800000 : -EINVAL));
+               break;
+       case PM8607_ID_LDO5:
+               ret = (index == 0) ? 2900000 :
+                       ((index == 1) ? 3000000 :
+                       ((index == 2) ? 3100000 : 3300000));
+               break;
+       case PM8607_ID_LDO7:
+       case PM8607_ID_LDO8:
+               ret = (index < 3) ? (index * 50000 + 1800000) :
+                       ((index < 8) ? (index * 50000 + 2550000) :
+                        -EINVAL);
+               break;
+       case PM8607_ID_LDO12:
+               ret = (index < 2) ? (index * 100000 + 1800000) :
+                       ((index < 7) ? (index * 100000 + 2500000) :
+                       ((index == 7) ? 3300000 : 1200000));
+               break;
+       case PM8607_ID_LDO2:
+       case PM8607_ID_LDO3:
+       case PM8607_ID_LDO9:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 8) ? (index * 50000 + 2550000) :
+                                -EINVAL);
+                       break;
+               case PM8607_CHIP_B0:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 7) ? (index * 50000 + 2550000) :
+                               3300000);
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO4:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 8) ? (index * 50000 + 2550000) :
+                                -EINVAL);
+                       break;
+               case PM8607_CHIP_B0:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 6) ? (index * 50000 + 2550000) :
+                               ((index == 6) ? 2900000 : 3300000));
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO6:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 8) ? (index * 50000 + 2450000) :
+                               -EINVAL);
+                       break;
+               case PM8607_CHIP_B0:
+                       ret = (index < 2) ? (index * 50000 + 1800000) :
+                               ((index < 7) ? (index * 50000 + 2500000) :
+                               3300000);
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO10:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 8) ? (index * 50000 + 2550000) :
+                               1200000);
+                       break;
+               case PM8607_CHIP_B0:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 7) ? (index * 50000 + 2550000) :
+                               ((index == 7) ? 3300000 : 1200000));
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO14:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       ret = (index < 3) ? (index * 50000 + 1800000) :
+                               ((index < 8) ? (index * 50000 + 2550000) :
+                                -EINVAL);
+                       break;
+               case PM8607_CHIP_B0:
+                       ret = (index < 2) ? (index * 50000 + 1800000) :
+                               ((index < 7) ? (index * 50000 + 2600000) :
+                               3300000);
+                       break;
+               }
+               break;
+       }
+       return ret;
+}
+
+static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       uint8_t chip_id = info->chip->chip_id;
+       int val = -ENOENT;
+       int ret;
+
+       switch (info->desc.id) {
+       case PM8607_ID_BUCK1:
+               if (min_uV >= 800000)           /* 800mV ~ 1500mV / 25mV */
+                       val = (min_uV - 775001) / 25000;
+               else {                          /* 25mV ~ 775mV / 25mV */
+                       val = (min_uV + 249999) / 25000;
+                       val += 32;
+               }
+               break;
+       case PM8607_ID_BUCK3:
+               if (info->slope_double)
+                       min_uV = min_uV >> 1;
+               val = (min_uV + 249999) / 25000; /* 0mV ~ 1500mV / 25mV */
+
+               break;
+       case PM8607_ID_LDO1:
+               if (min_uV > 1800000)
+                       val = 2;
+               else if (min_uV > 1200000)
+                       val = 0;
+               else
+                       val = 1;
+               break;
+       case PM8607_ID_LDO5:
+               if (min_uV > 3100000)
+                       val = 3;
+               else                            /* 2900mV ~ 3100mV / 100mV */
+                       val = (min_uV - 2800001) / 100000;
+               break;
+       case PM8607_ID_LDO7:
+       case PM8607_ID_LDO8:
+               if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+                       if (min_uV <= 1800000)
+                               val = 0;        /* 1800mv */
+                       else if (min_uV <= 1900000)
+                               val = (min_uV - 1750001) / 50000;
+                       else
+                               val = 3;        /* 2700mV */
+               } else {                 /* 2700mV ~ 2900mV / 50mV */
+                       if (min_uV <= 2900000) {
+                               val = (min_uV - 2650001) / 50000;
+                               val += 3;
+                       } else
+                               val = -EINVAL;
+               }
+               break;
+       case PM8607_ID_LDO10:
+               if (min_uV > 2850000)
+                       val = 7;
+               else if (min_uV <= 1200000)
+                       val = 8;
+               else if (min_uV < 2700000)      /* 1800mV ~ 1900mV / 50mV */
+                       val = (min_uV - 1750001) / 50000;
+               else {                          /* 2700mV ~ 2850mV / 50mV */
+                       val = (min_uV - 2650001) / 50000;
+                       val += 3;
+               }
+               break;
+       case PM8607_ID_LDO12:
+               if (min_uV < 2700000) {         /* 1800mV ~ 1900mV / 100mV */
+                       if (min_uV <= 1200000)
+                               val = 8;        /* 1200mV */
+                       else if (min_uV <= 1800000)
+                               val = 0;        /* 1800mV */
+                       else if (min_uV <= 1900000)
+                               val = (min_uV - 1700001) / 100000;
+                       else
+                               val = 2;        /* 2700mV */
+               } else {                        /* 2700mV ~ 3100mV / 100mV */
+                       if (min_uV <= 3100000) {
+                               val = (min_uV - 2600001) / 100000;
+                               val += 2;
+                       } else if (min_uV <= 3300000)
+                               val = 7;
+                       else
+                               val = -EINVAL;
+               }
+               break;
+       case PM8607_ID_LDO2:
+       case PM8607_ID_LDO3:
+       case PM8607_ID_LDO9:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       if (min_uV < 2700000)   /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2700mV */
+                       else {                  /* 2700mV ~ 2900mV / 50mV */
+                               if (min_uV <= 2900000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 3;
+                               } else
+                                       val = -EINVAL;
+                       }
+                       break;
+               case PM8607_CHIP_B0:
+                       if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2700mV */
+                       } else {                 /* 2700mV ~ 2850mV / 50mV */
+                               if (min_uV <= 2850000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 3;
+                               } else if (min_uV <= 3300000)
+                                       val = 7;
+                               else
+                                       val = -EINVAL;
+                       }
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO4:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       if (min_uV < 2700000)   /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2700mV */
+                       else {                  /* 2700mV ~ 2900mV / 50mV */
+                               if (min_uV <= 2900000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 3;
+                               } else
+                                       val = -EINVAL;
+                       }
+                       break;
+               case PM8607_CHIP_B0:
+                       if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2700mV */
+                       } else {                 /* 2700mV ~ 2800mV / 50mV */
+                               if (min_uV <= 2850000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 3;
+                               } else if (min_uV <= 2900000)
+                                       val = 6;
+                               else if (min_uV <= 3300000)
+                                       val = 7;
+                               else
+                                       val = -EINVAL;
+                       }
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO6:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       if (min_uV < 2600000) { /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2600mV */
+                       } else {                /* 2600mV ~ 2800mV / 50mV */
+                               if (min_uV <= 2800000) {
+                                       val = (min_uV - 2550001) / 50000;
+                                       val += 3;
+                               } else
+                                       val = -EINVAL;
+                       }
+                       break;
+               case PM8607_CHIP_B0:
+                       if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1850000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 2;        /* 2600mV */
+                       } else {                /* 2600mV ~ 2800mV / 50mV */
+                               if (min_uV <= 2800000) {
+                                       val = (min_uV - 2550001) / 50000;
+                                       val += 2;
+                               } else if (min_uV <= 3300000)
+                                       val = 7;
+                               else
+                                       val = -EINVAL;
+                       }
+                       break;
+               }
+               break;
+       case PM8607_ID_LDO14:
+               switch (chip_id) {
+               case PM8607_CHIP_A0:
+               case PM8607_CHIP_A1:
+                       if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1900000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 3;        /* 2700mV */
+                       } else {                 /* 2700mV ~ 2900mV / 50mV */
+                               if (min_uV <= 2900000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 3;
+                               } else
+                                       val = -EINVAL;
+                       }
+                       break;
+               case PM8607_CHIP_B0:
+                       if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */
+                               if (min_uV <= 1800000)
+                                       val = 0;
+                               else if (min_uV <= 1850000)
+                                       val = (min_uV - 1750001) / 50000;
+                               else
+                                       val = 2;        /* 2700mV */
+                       } else {                 /* 2700mV ~ 2900mV / 50mV */
+                               if (min_uV <= 2900000) {
+                                       val = (min_uV - 2650001) / 50000;
+                                       val += 2;
+                               } else if (min_uV <= 3300000)
+                                       val = 7;
+                               else
+                                       val = -EINVAL;
+                       }
+                       break;
+               }
+               break;
+       }
+       if (val >= 0) {
+               ret = pm8607_list_voltage(rdev, val);
+               if (ret > max_uV) {
+                       pr_err("exceed voltage range (%d %d) uV",
+                               min_uV, max_uV);
+                       return -EINVAL;
+               }
+       } else
+               pr_err("invalid voltage range (%d %d) uV", min_uV, max_uV);
+       return val;
+}
+
+static int pm8607_set_voltage(struct regulator_dev *rdev,
+                             int min_uV, int max_uV)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       struct pm8607_chip *chip = info->chip;
+       uint8_t val, mask;
+       int ret;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       ret = choose_voltage(rdev, min_uV, max_uV);
+       if (ret < 0)
+               return -EINVAL;
+       val = (uint8_t)(ret << info->vol_shift);
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       ret = pm8607_set_bits(chip, info->vol_reg, mask, val);
+       if (ret)
+               return ret;
+       switch (info->desc.id) {
+       case PM8607_ID_BUCK1:
+       case PM8607_ID_BUCK3:
+               ret = pm8607_set_bits(chip, info->update_reg,
+                                     1 << info->update_bit,
+                                     1 << info->update_bit);
+               break;
+       }
+       return ret;
+}
+
+static int pm8607_get_voltage(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       struct pm8607_chip *chip = info->chip;
+       uint8_t val, mask;
+       int ret;
+
+       ret = pm8607_reg_read(chip, info->vol_reg);
+       if (ret < 0)
+               return ret;
+
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val = ((unsigned char)ret & mask) >> info->vol_shift;
+
+       return pm8607_list_voltage(rdev, val);
+}
+
+static int pm8607_enable(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       struct pm8607_chip *chip = info->chip;
+
+       return pm8607_set_bits(chip, info->enable_reg,
+                              1 << info->enable_bit,
+                              1 << info->enable_bit);
+}
+
+static int pm8607_disable(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       struct pm8607_chip *chip = info->chip;
+
+       return pm8607_set_bits(chip, info->enable_reg,
+                              1 << info->enable_bit, 0);
+}
+
+static int pm8607_is_enabled(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       struct pm8607_chip *chip = info->chip;
+       int ret;
+
+       ret = pm8607_reg_read(chip, info->enable_reg);
+       if (ret < 0)
+               return ret;
+
+       return !!((unsigned char)ret & (1 << info->enable_bit));
+}
+
+static struct regulator_ops pm8607_regulator_ops = {
+       .set_voltage    = pm8607_set_voltage,
+       .get_voltage    = pm8607_get_voltage,
+       .enable         = pm8607_enable,
+       .disable        = pm8607_disable,
+       .is_enabled     = pm8607_is_enabled,
+};
+
+#define PM8607_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = "BUCK" #_id,                                  \
+               .ops    = &pm8607_regulator_ops,                        \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = PM8607_ID_BUCK##_id,                          \
+               .owner  = THIS_MODULE,                                  \
+       },                                                              \
+       .min_uV         = (min) * 1000,                                 \
+       .max_uV         = (max) * 1000,                                 \
+       .step_uV        = (step) * 1000,                                \
+       .vol_reg        = PM8607_##vreg,                                \
+       .vol_shift      = (0),                                          \
+       .vol_nbits      = (nbits),                                      \
+       .update_reg     = PM8607_##ureg,                                \
+       .update_bit     = (ubit),                                       \
+       .enable_reg     = PM8607_##ereg,                                \
+       .enable_bit     = (ebit),                                       \
+       .slope_double   = (0),                                          \
+}
+
+#define PM8607_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = "LDO" #_id,                                   \
+               .ops    = &pm8607_regulator_ops,                        \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = PM8607_ID_LDO##_id,                           \
+               .owner  = THIS_MODULE,                                  \
+       },                                                              \
+       .min_uV         = (min) * 1000,                                 \
+       .max_uV         = (max) * 1000,                                 \
+       .step_uV        = (step) * 1000,                                \
+       .vol_reg        = PM8607_##vreg,                                \
+       .vol_shift      = (shift),                                      \
+       .vol_nbits      = (nbits),                                      \
+       .enable_reg     = PM8607_##ereg,                                \
+       .enable_bit     = (ebit),                                       \
+       .slope_double   = (0),                                          \
+}
+
+static struct pm8607_regulator_info pm8607_regulator_info[] = {
+       PM8607_DVC(1, 0, 1500, 25, BUCK1, 6, GO, 0, SUPPLIES_EN11, 0),
+       PM8607_DVC(3, 0, 1500, 25, BUCK3, 6, GO, 2, SUPPLIES_EN11, 2),
+
+       PM8607_LDO(1 , 1200, 2800, 0, LDO1 , 0, 2, SUPPLIES_EN11, 3),
+       PM8607_LDO(2 , 1800, 3300, 0, LDO2 , 0, 3, SUPPLIES_EN11, 4),
+       PM8607_LDO(3 , 1800, 3300, 0, LDO3 , 0, 3, SUPPLIES_EN11, 5),
+       PM8607_LDO(4 , 1800, 3300, 0, LDO4 , 0, 3, SUPPLIES_EN11, 6),
+       PM8607_LDO(5 , 2900, 3300, 0, LDO5 , 0, 2, SUPPLIES_EN11, 7),
+       PM8607_LDO(6 , 1800, 3300, 0, LDO6 , 0, 3, SUPPLIES_EN12, 0),
+       PM8607_LDO(7 , 1800, 2900, 0, LDO7 , 0, 3, SUPPLIES_EN12, 1),
+       PM8607_LDO(8 , 1800, 2900, 0, LDO8 , 0, 3, SUPPLIES_EN12, 2),
+       PM8607_LDO(9 , 1800, 3300, 0, LDO9 , 0, 3, SUPPLIES_EN12, 3),
+       PM8607_LDO(10, 1200, 3300, 0, LDO10, 0, 4, SUPPLIES_EN11, 4),
+       PM8607_LDO(12, 1200, 3300, 0, LDO12, 0, 4, SUPPLIES_EN11, 5),
+       PM8607_LDO(14, 1800, 3300, 0, LDO14, 0, 3, SUPPLIES_EN11, 6),
+};
+
+static inline struct pm8607_regulator_info *find_regulator_info(int id)
+{
+       struct pm8607_regulator_info *info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
+               info = &pm8607_regulator_info[i];
+               if (info->desc.id == id)
+                       return info;
+       }
+       return NULL;
+}
+
+static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+{
+       struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct pm8607_platform_data *pdata = chip->dev->platform_data;
+       struct pm8607_regulator_info *info = NULL;
+
+       info = find_regulator_info(pdev->id);
+       if (info == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       info->chip = chip;
+
+       info->regulator = regulator_register(&info->desc, &pdev->dev,
+                                            pdata->regulator[pdev->id], info);
+       if (IS_ERR(info->regulator)) {
+               dev_err(&pdev->dev, "failed to register regulator %s\n",
+                       info->desc.name);
+               return PTR_ERR(info->regulator);
+       }
+
+       /* check DVC ramp slope double */
+       if (info->desc.id == PM8607_ID_BUCK3)
+               if (info->chip->buck3_double)
+                       info->slope_double = 1;
+
+       platform_set_drvdata(pdev, info);
+       return 0;
+}
+
+static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+{
+       struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
+
+       regulator_unregister(info->regulator);
+       return 0;
+}
+
+#define PM8607_REGULATOR_DRIVER(_name)                         \
+{                                                              \
+       .driver         = {                                     \
+               .name   = "88pm8607-" #_name,                   \
+               .owner  = THIS_MODULE,                          \
+       },                                                      \
+       .probe          = pm8607_regulator_probe,               \
+       .remove         = __devexit_p(pm8607_regulator_remove), \
+}
+
+static struct platform_driver pm8607_regulator_driver[] = {
+       PM8607_REGULATOR_DRIVER(buck1),
+       PM8607_REGULATOR_DRIVER(buck2),
+       PM8607_REGULATOR_DRIVER(buck3),
+       PM8607_REGULATOR_DRIVER(ldo1),
+       PM8607_REGULATOR_DRIVER(ldo2),
+       PM8607_REGULATOR_DRIVER(ldo3),
+       PM8607_REGULATOR_DRIVER(ldo4),
+       PM8607_REGULATOR_DRIVER(ldo5),
+       PM8607_REGULATOR_DRIVER(ldo6),
+       PM8607_REGULATOR_DRIVER(ldo7),
+       PM8607_REGULATOR_DRIVER(ldo8),
+       PM8607_REGULATOR_DRIVER(ldo9),
+       PM8607_REGULATOR_DRIVER(ldo10),
+       PM8607_REGULATOR_DRIVER(ldo12),
+       PM8607_REGULATOR_DRIVER(ldo14),
+};
+
+static int __init pm8607_regulator_init(void)
+{
+       int i, count, ret;
+
+       count = ARRAY_SIZE(pm8607_regulator_driver);
+       for (i = 0; i < count; i++) {
+               ret = platform_driver_register(&pm8607_regulator_driver[i]);
+               if (ret != 0)
+                       pr_err("Failed to register regulator driver: %d\n",
+                               ret);
+       }
+       return 0;
+}
+subsys_initcall(pm8607_regulator_init);
+
+static void __exit pm8607_regulator_exit(void)
+{
+       int i, count;
+
+       count = ARRAY_SIZE(pm8607_regulator_driver);
+       for (i = 0; i < count; i++)
+               platform_driver_unregister(&pm8607_regulator_driver[i]);
+}
+module_exit(pm8607_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
+MODULE_ALIAS("platform:88pm8607-regulator");
index 7cfdd65..262f62e 100644 (file)
@@ -69,6 +69,13 @@ config REGULATOR_MAX1586
          regulator via I2C bus. The provided regulator is suitable
          for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX8660
+       tristate "Maxim 8660/8661 voltage regulator"
+       depends on I2C
+       help
+         This driver controls a Maxim 8660/8661 voltage output
+         regulator via I2C bus.
+
 config REGULATOR_TWL4030
        bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
        depends on TWL4030_CORE
@@ -157,5 +164,11 @@ config REGULATOR_TPS6507X
          three step-down converters and two general-purpose LDO voltage regulators.
          It supports TI's software based Class-2 SmartReflex implementation.
 
+config REGULATOR_88PM8607
+       bool "Marvell 88PM8607 Power regulators"
+       depends on MFD_88PM8607=y
+       help
+         This driver supports 88PM8607 voltage regulator chips.
+
 endif
 
index 9ae3cc4..b3c806c 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
@@ -20,10 +21,11 @@ obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
-obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o
+obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
+obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
index 49aeee8..b349db4 100644 (file)
@@ -81,7 +81,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
 #define LDO_C_VOLTAGE 2650000
 #define LDO_D_VOLTAGE 2650000
 
-static const int const ldo_e_buck_typ_voltages[] = {
+static const int ldo_e_buck_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -91,7 +91,7 @@ static const int const ldo_e_buck_typ_voltages[] = {
        900000,
 };
 
-static const int const ldo_f_typ_voltages[] = {
+static const int ldo_f_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -102,21 +102,21 @@ static const int const ldo_f_typ_voltages[] = {
        2650000,
 };
 
-static const int const ldo_g_typ_voltages[] = {
+static const int ldo_g_typ_voltages[] = {
        2850000,
        2750000,
        1800000,
        1500000,
 };
 
-static const int const ldo_h_typ_voltages[] = {
+static const int ldo_h_typ_voltages[] = {
        2750000,
        1800000,
        1500000,
        1200000,
 };
 
-static const int const ldo_k_typ_voltages[] = {
+static const int ldo_k_typ_voltages[] = {
        2750000,
        1800000,
 };
@@ -241,24 +241,12 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
         * LDO D is a special regulator. When it is disabled, the entire
         * system is shut down. So this is handled specially.
         */
+       pr_info("Called ab3100_disable_regulator\n");
        if (abreg->regreg == AB3100_LDO_D) {
-               int i;
-
                dev_info(&reg->dev, "disabling LDO D - shut down system\n");
-               /*
-                * Set regulators to default values, ignore any errors,
-                * we're going DOWN
-                */
-               for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
-                       (void) ab3100_set_register_interruptible(abreg->ab3100,
-                                       ab3100_reg_init_order[i],
-                                       abreg->plfdata->reg_initvals[i]);
-               }
-
                /* Setting LDO D to 0x00 cuts the power to the SoC */
                return ab3100_set_register_interruptible(abreg->ab3100,
                                                         AB3100_LDO_D, 0x00U);
-
        }
 
        /*
@@ -607,13 +595,6 @@ static int __init ab3100_regulators_probe(struct platform_device *pdev)
                }
        }
 
-       if (err) {
-               dev_err(&pdev->dev,
-                       "LDO D regulator initialization failed with error %d\n",
-                       err);
-               return err;
-       }
-
        /* Register the regulators */
        for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
                struct ab3100_regulator *reg = &ab3100_regulators[i];
@@ -688,7 +669,7 @@ static __init int ab3100_regulators_init(void)
 
 static __exit void ab3100_regulators_exit(void)
 {
-       platform_driver_register(&ab3100_regulators_driver);
+       platform_driver_unregister(&ab3100_regulators_driver);
 }
 
 subsys_initcall(ab3100_regulators_init);
index efe568d..686ef27 100644 (file)
@@ -66,6 +66,16 @@ static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
 static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
 
+static const char *rdev_get_name(struct regulator_dev *rdev)
+{
+       if (rdev->constraints && rdev->constraints->name)
+               return rdev->constraints->name;
+       else if (rdev->desc->name)
+               return rdev->desc->name;
+       else
+               return "";
+}
+
 /* gets the regulator for a given consumer device */
 static struct regulator *get_device_regulator(struct device *dev)
 {
@@ -96,12 +106,12 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
 
        if (!rdev->constraints) {
                printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-                      rdev->desc->name);
+                      rdev_get_name(rdev));
                return -ENODEV;
        }
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
                printk(KERN_ERR "%s: operation not allowed for %s\n",
-                      __func__, rdev->desc->name);
+                      __func__, rdev_get_name(rdev));
                return -EPERM;
        }
 
@@ -124,12 +134,12 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
 
        if (!rdev->constraints) {
                printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-                      rdev->desc->name);
+                      rdev_get_name(rdev));
                return -ENODEV;
        }
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
                printk(KERN_ERR "%s: operation not allowed for %s\n",
-                      __func__, rdev->desc->name);
+                      __func__, rdev_get_name(rdev));
                return -EPERM;
        }
 
@@ -159,17 +169,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
 
        if (!rdev->constraints) {
                printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-                      rdev->desc->name);
+                      rdev_get_name(rdev));
                return -ENODEV;
        }
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
                printk(KERN_ERR "%s: operation not allowed for %s\n",
-                      __func__, rdev->desc->name);
+                      __func__, rdev_get_name(rdev));
                return -EPERM;
        }
        if (!(rdev->constraints->valid_modes_mask & mode)) {
                printk(KERN_ERR "%s: invalid mode %x for %s\n",
-                      __func__, mode, rdev->desc->name);
+                      __func__, mode, rdev_get_name(rdev));
                return -EINVAL;
        }
        return 0;
@@ -180,12 +190,12 @@ static int regulator_check_drms(struct regulator_dev *rdev)
 {
        if (!rdev->constraints) {
                printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-                      rdev->desc->name);
+                      rdev_get_name(rdev));
                return -ENODEV;
        }
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
                printk(KERN_ERR "%s: operation not allowed for %s\n",
-                      __func__, rdev->desc->name);
+                      __func__, rdev_get_name(rdev));
                return -EPERM;
        }
        return 0;
@@ -230,16 +240,8 @@ static ssize_t regulator_name_show(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
        struct regulator_dev *rdev = dev_get_drvdata(dev);
-       const char *name;
 
-       if (rdev->constraints && rdev->constraints->name)
-               name = rdev->constraints->name;
-       else if (rdev->desc->name)
-               name = rdev->desc->name;
-       else
-               name = "";
-
-       return sprintf(buf, "%s\n", name);
+       return sprintf(buf, "%s\n", rdev_get_name(rdev));
 }
 
 static ssize_t regulator_print_opmode(char *buf, int mode)
@@ -388,7 +390,7 @@ static ssize_t regulator_total_uA_show(struct device *dev,
 
        mutex_lock(&rdev->mutex);
        list_for_each_entry(regulator, &rdev->consumer_list, list)
-           uA += regulator->uA_load;
+               uA += regulator->uA_load;
        mutex_unlock(&rdev->mutex);
        return sprintf(buf, "%d\n", uA);
 }
@@ -563,7 +565,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
 
        /* calc total requested load */
        list_for_each_entry(sibling, &rdev->consumer_list, list)
-           current_uA += sibling->uA_load;
+               current_uA += sibling->uA_load;
 
        /* now get the optimum mode for our new total regulator load */
        mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
@@ -579,10 +581,29 @@ static int suspend_set_state(struct regulator_dev *rdev,
        struct regulator_state *rstate)
 {
        int ret = 0;
+       bool can_set_state;
 
-       /* enable & disable are mandatory for suspend control */
-       if (!rdev->desc->ops->set_suspend_enable ||
-               !rdev->desc->ops->set_suspend_disable) {
+       can_set_state = rdev->desc->ops->set_suspend_enable &&
+               rdev->desc->ops->set_suspend_disable;
+
+       /* If we have no suspend mode configration don't set anything;
+        * only warn if the driver actually makes the suspend mode
+        * configurable.
+        */
+       if (!rstate->enabled && !rstate->disabled) {
+               if (can_set_state)
+                       printk(KERN_WARNING "%s: No configuration for %s\n",
+                              __func__, rdev_get_name(rdev));
+               return 0;
+       }
+
+       if (rstate->enabled && rstate->disabled) {
+               printk(KERN_ERR "%s: invalid configuration for %s\n",
+                      __func__, rdev_get_name(rdev));
+               return -EINVAL;
+       }
+
+       if (!can_set_state) {
                printk(KERN_ERR "%s: no way to set suspend state\n",
                        __func__);
                return -EINVAL;
@@ -641,25 +662,43 @@ static void print_constraints(struct regulator_dev *rdev)
 {
        struct regulation_constraints *constraints = rdev->constraints;
        char buf[80];
-       int count;
+       int count = 0;
+       int ret;
 
-       if (rdev->desc->type == REGULATOR_VOLTAGE) {
+       if (constraints->min_uV && constraints->max_uV) {
                if (constraints->min_uV == constraints->max_uV)
-                       count = sprintf(buf, "%d mV ",
-                                       constraints->min_uV / 1000);
+                       count += sprintf(buf + count, "%d mV ",
+                                        constraints->min_uV / 1000);
                else
-                       count = sprintf(buf, "%d <--> %d mV ",
-                                       constraints->min_uV / 1000,
-                                       constraints->max_uV / 1000);
-       } else {
+                       count += sprintf(buf + count, "%d <--> %d mV ",
+                                        constraints->min_uV / 1000,
+                                        constraints->max_uV / 1000);
+       }
+
+       if (!constraints->min_uV ||
+           constraints->min_uV != constraints->max_uV) {
+               ret = _regulator_get_voltage(rdev);
+               if (ret > 0)
+                       count += sprintf(buf + count, "at %d mV ", ret / 1000);
+       }
+
+       if (constraints->min_uA && constraints->max_uA) {
                if (constraints->min_uA == constraints->max_uA)
-                       count = sprintf(buf, "%d mA ",
-                                       constraints->min_uA / 1000);
+                       count += sprintf(buf + count, "%d mA ",
+                                        constraints->min_uA / 1000);
                else
-                       count = sprintf(buf, "%d <--> %d mA ",
-                                       constraints->min_uA / 1000,
-                                       constraints->max_uA / 1000);
+                       count += sprintf(buf + count, "%d <--> %d mA ",
+                                        constraints->min_uA / 1000,
+                                        constraints->max_uA / 1000);
        }
+
+       if (!constraints->min_uA ||
+           constraints->min_uA != constraints->max_uA) {
+               ret = _regulator_get_current_limit(rdev);
+               if (ret > 0)
+                       count += sprintf(buf + count, "at %d uA ", ret / 1000);
+       }
+
        if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
                count += sprintf(buf + count, "fast ");
        if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
@@ -669,33 +708,30 @@ static void print_constraints(struct regulator_dev *rdev)
        if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
                count += sprintf(buf + count, "standby");
 
-       printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
+       printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf);
 }
 
-/**
- * set_machine_constraints - sets regulator constraints
- * @rdev: regulator source
- * @constraints: constraints to apply
- *
- * Allows platform initialisation code to define and constrain
- * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
- * Constraints *must* be set by platform code in order for some
- * regulator operations to proceed i.e. set_voltage, set_current_limit,
- * set_mode.
- */
-static int set_machine_constraints(struct regulator_dev *rdev,
+static int machine_constraints_voltage(struct regulator_dev *rdev,
        struct regulation_constraints *constraints)
 {
-       int ret = 0;
-       const char *name;
        struct regulator_ops *ops = rdev->desc->ops;
+       const char *name = rdev_get_name(rdev);
+       int ret;
 
-       if (constraints->name)
-               name = constraints->name;
-       else if (rdev->desc->name)
-               name = rdev->desc->name;
-       else
-               name = "regulator";
+       /* do we need to apply the constraint voltage */
+       if (rdev->constraints->apply_uV &&
+               rdev->constraints->min_uV == rdev->constraints->max_uV &&
+               ops->set_voltage) {
+               ret = ops->set_voltage(rdev,
+                       rdev->constraints->min_uV, rdev->constraints->max_uV);
+                       if (ret < 0) {
+                               printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
+                                      __func__,
+                                      rdev->constraints->min_uV, name);
+                               rdev->constraints = NULL;
+                               return ret;
+                       }
+       }
 
        /* constrain machine-level voltage specs to fit
         * the actual range supported by this regulator.
@@ -719,14 +755,13 @@ static int set_machine_constraints(struct regulator_dev *rdev,
 
                /* voltage constraints are optional */
                if ((cmin == 0) && (cmax == 0))
-                       goto out;
+                       return 0;
 
                /* else require explicit machine-level constraints */
                if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
                        pr_err("%s: %s '%s' voltage constraints\n",
                                       __func__, "invalid", name);
-                       ret = -EINVAL;
-                       goto out;
+                       return -EINVAL;
                }
 
                /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
@@ -748,8 +783,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                if (max_uV < min_uV) {
                        pr_err("%s: %s '%s' voltage constraints\n",
                                       __func__, "unsupportable", name);
-                       ret = -EINVAL;
-                       goto out;
+                       return -EINVAL;
                }
 
                /* use regulator's subset of machine constraints */
@@ -767,22 +801,34 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                }
        }
 
+       return 0;
+}
+
+/**
+ * set_machine_constraints - sets regulator constraints
+ * @rdev: regulator source
+ * @constraints: constraints to apply
+ *
+ * Allows platform initialisation code to define and constrain
+ * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
+ * Constraints *must* be set by platform code in order for some
+ * regulator operations to proceed i.e. set_voltage, set_current_limit,
+ * set_mode.
+ */
+static int set_machine_constraints(struct regulator_dev *rdev,
+       struct regulation_constraints *constraints)
+{
+       int ret = 0;
+       const char *name;
+       struct regulator_ops *ops = rdev->desc->ops;
+
        rdev->constraints = constraints;
 
-       /* do we need to apply the constraint voltage */
-       if (rdev->constraints->apply_uV &&
-               rdev->constraints->min_uV == rdev->constraints->max_uV &&
-               ops->set_voltage) {
-               ret = ops->set_voltage(rdev,
-                       rdev->constraints->min_uV, rdev->constraints->max_uV);
-                       if (ret < 0) {
-                               printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
-                                      __func__,
-                                      rdev->constraints->min_uV, name);
-                               rdev->constraints = NULL;
-                               goto out;
-                       }
-       }
+       name = rdev_get_name(rdev);
+
+       ret = machine_constraints_voltage(rdev, constraints);
+       if (ret != 0)
+               goto out;
 
        /* do we need to setup our suspend state */
        if (constraints->initial_state) {
@@ -903,7 +949,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
                                dev_name(&node->regulator->dev),
                                node->regulator->desc->name,
                                supply,
-                               dev_name(&rdev->dev), rdev->desc->name);
+                               dev_name(&rdev->dev), rdev_get_name(rdev));
                return -EBUSY;
        }
 
@@ -1212,7 +1258,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
                ret = _regulator_enable(rdev->supply);
                if (ret < 0) {
                        printk(KERN_ERR "%s: failed to enable %s: %d\n",
-                              __func__, rdev->desc->name, ret);
+                              __func__, rdev_get_name(rdev), ret);
                        return ret;
                }
        }
@@ -1238,7 +1284,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
                        }
                } else if (ret < 0) {
                        printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
-                              __func__, rdev->desc->name, ret);
+                              __func__, rdev_get_name(rdev), ret);
                        return ret;
                }
                /* Fallthrough on positive return values - already enabled */
@@ -1279,7 +1325,7 @@ static int _regulator_disable(struct regulator_dev *rdev)
 
        if (WARN(rdev->use_count <= 0,
                        "unbalanced disables for %s\n",
-                       rdev->desc->name))
+                       rdev_get_name(rdev)))
                return -EIO;
 
        /* are we the last user and permitted to disable ? */
@@ -1292,7 +1338,7 @@ static int _regulator_disable(struct regulator_dev *rdev)
                        ret = rdev->desc->ops->disable(rdev);
                        if (ret < 0) {
                                printk(KERN_ERR "%s: failed to disable %s\n",
-                                      __func__, rdev->desc->name);
+                                      __func__, rdev_get_name(rdev));
                                return ret;
                        }
                }
@@ -1349,7 +1395,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
                ret = rdev->desc->ops->disable(rdev);
                if (ret < 0) {
                        printk(KERN_ERR "%s: failed to force disable %s\n",
-                              __func__, rdev->desc->name);
+                              __func__, rdev_get_name(rdev));
                        return ret;
                }
                /* notify other consumers that power has been forced off */
@@ -1766,7 +1812,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        output_uV = rdev->desc->ops->get_voltage(rdev);
        if (output_uV <= 0) {
                printk(KERN_ERR "%s: invalid output voltage found for %s\n",
-                       __func__, rdev->desc->name);
+                       __func__, rdev_get_name(rdev));
                goto out;
        }
 
@@ -1777,13 +1823,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0) {
                printk(KERN_ERR "%s: invalid input voltage found for %s\n",
-                       __func__, rdev->desc->name);
+                       __func__, rdev_get_name(rdev));
                goto out;
        }
 
        /* calc total requested load for this regulator */
        list_for_each_entry(consumer, &rdev->consumer_list, list)
-           total_uA_load += consumer->uA_load;
+               total_uA_load += consumer->uA_load;
 
        mode = rdev->desc->ops->get_optimum_mode(rdev,
                                                 input_uV, output_uV,
@@ -1791,7 +1837,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        ret = regulator_check_mode(rdev, mode);
        if (ret < 0) {
                printk(KERN_ERR "%s: failed to get optimum mode for %s @"
-                       " %d uA %d -> %d uV\n", __func__, rdev->desc->name,
+                       " %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev),
                        total_uA_load, input_uV, output_uV);
                goto out;
        }
@@ -1799,7 +1845,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        ret = rdev->desc->ops->set_mode(rdev, mode);
        if (ret < 0) {
                printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n",
-                       __func__, mode, rdev->desc->name);
+                       __func__, mode, rdev_get_name(rdev));
                goto out;
        }
        ret = mode;
@@ -1852,9 +1898,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
 
        /* now notify regulator we supply */
        list_for_each_entry(_rdev, &rdev->supply_list, slist) {
-         mutex_lock(&_rdev->mutex);
-         _notifier_call_chain(_rdev, event, data);
-         mutex_unlock(&_rdev->mutex);
+               mutex_lock(&_rdev->mutex);
+               _notifier_call_chain(_rdev, event, data);
+               mutex_unlock(&_rdev->mutex);
        }
 }
 
@@ -1885,9 +1931,9 @@ int regulator_bulk_get(struct device *dev, int num_consumers,
                consumers[i].consumer = regulator_get(dev,
                                                      consumers[i].supply);
                if (IS_ERR(consumers[i].consumer)) {
-                       dev_err(dev, "Failed to get supply '%s'\n",
-                               consumers[i].supply);
                        ret = PTR_ERR(consumers[i].consumer);
+                       dev_err(dev, "Failed to get supply '%s': %d\n",
+                               consumers[i].supply, ret);
                        consumers[i].consumer = NULL;
                        goto err;
                }
@@ -1930,8 +1976,8 @@ int regulator_bulk_enable(int num_consumers,
        return 0;
 
 err:
-       printk(KERN_ERR "Failed to enable %s\n", consumers[i].supply);
-       for (i = 0; i < num_consumers; i++)
+       printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret);
+       for (--i; i >= 0; --i)
                regulator_disable(consumers[i].consumer);
 
        return ret;
@@ -1965,8 +2011,9 @@ int regulator_bulk_disable(int num_consumers,
        return 0;
 
 err:
-       printk(KERN_ERR "Failed to disable %s\n", consumers[i].supply);
-       for (i = 0; i < num_consumers; i++)
+       printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply,
+              ret);
+       for (--i; i >= 0; --i)
                regulator_enable(consumers[i].consumer);
 
        return ret;
@@ -2316,7 +2363,7 @@ int regulator_suspend_prepare(suspend_state_t state)
 
                if (ret < 0) {
                        printk(KERN_ERR "%s: failed to prepare %s\n",
-                               __func__, rdev->desc->name);
+                               __func__, rdev_get_name(rdev));
                        goto out;
                }
        }
@@ -2429,12 +2476,7 @@ static int __init regulator_init_complete(void)
                ops = rdev->desc->ops;
                c = rdev->constraints;
 
-               if (c && c->name)
-                       name = c->name;
-               else if (rdev->desc->name)
-                       name = rdev->desc->name;
-               else
-                       name = "regulator";
+               name = rdev_get_name(rdev);
 
                if (!ops->disable || (c && c->always_on))
                        continue;
index aa224d9..f8c4661 100644 (file)
@@ -331,7 +331,7 @@ static int da9034_get_ldo12_voltage(struct regulator_dev *rdev)
 static int da9034_list_ldo12_voltage(struct regulator_dev *rdev,
                                     unsigned selector)
 {
-       if (selector > ARRAY_SIZE(da9034_ldo12_data))
+       if (selector >= ARRAY_SIZE(da9034_ldo12_data))
                return -EINVAL;
        return da9034_ldo12_data[selector] * 1000;
 }
index 7803a32..76d08c2 100644 (file)
@@ -446,8 +446,8 @@ static int setup_regulators(struct lp3971 *lp3971,
                lp3971->rdev[i] = regulator_register(&regulators[id],
                        lp3971->dev, pdata->regulators[i].initdata, lp3971);
 
-               err = IS_ERR(lp3971->rdev[i]);
-               if (err) {
+               if (IS_ERR(lp3971->rdev[i])) {
+                       err = PTR_ERR(lp3971->rdev[i]);
                        dev_err(lp3971->dev, "regulator init failed: %d\n",
                                err);
                        goto error;
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
new file mode 100644 (file)
index 0000000..acc2fb7
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * max8660.c  --  Voltage regulation for the Maxim 8660/8661
+ *
+ * based on max1586.c and wm8400-regulator.c
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * 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
+ *
+ * Some info:
+ *
+ * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8660-MAX8661.pdf
+ *
+ * This chip is a bit nasty because it is a write-only device. Thus, the driver
+ * uses shadow registers to keep track of its values. The main problem appears
+ * to be the initialization: When Linux boots up, we cannot know if the chip is
+ * in the default state or not, so we would have to pass such information in
+ * platform_data. As this adds a bit of complexity to the driver, this is left
+ * out for now until it is really needed.
+ *
+ * [A|S|M]DTV1 registers are currently not used, but [A|S|M]DTV2.
+ *
+ * If the driver is feature complete, it might be worth to check if one set of
+ * functions for V3-V7 is sufficient. For maximum flexibility during
+ * development, they are separated for now.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/max8660.h>
+
+#define MAX8660_DCDC_MIN_UV     725000
+#define MAX8660_DCDC_MAX_UV    1800000
+#define MAX8660_DCDC_STEP        25000
+#define MAX8660_DCDC_MAX_SEL   0x2b
+
+#define MAX8660_LDO5_MIN_UV    1700000
+#define MAX8660_LDO5_MAX_UV    2000000
+#define MAX8660_LDO5_STEP        25000
+#define MAX8660_LDO5_MAX_SEL   0x0c
+
+#define MAX8660_LDO67_MIN_UV   1800000
+#define MAX8660_LDO67_MAX_UV   3300000
+#define MAX8660_LDO67_STEP      100000
+#define MAX8660_LDO67_MAX_SEL  0x0f
+
+enum {
+       MAX8660_OVER1,
+       MAX8660_OVER2,
+       MAX8660_VCC1,
+       MAX8660_ADTV1,
+       MAX8660_ADTV2,
+       MAX8660_SDTV1,
+       MAX8660_SDTV2,
+       MAX8660_MDTV1,
+       MAX8660_MDTV2,
+       MAX8660_L12VCR,
+       MAX8660_FPWM,
+       MAX8660_N_REGS, /* not a real register */
+};
+
+struct max8660 {
+       struct i2c_client *client;
+       u8 shadow_regs[MAX8660_N_REGS];         /* as chip is write only */
+       struct regulator_dev *rdev[];
+};
+
+static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val)
+{
+       static const u8 max8660_addresses[MAX8660_N_REGS] =
+         { 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80 };
+
+       int ret;
+       u8 reg_val = (max8660->shadow_regs[reg] & mask) | val;
+       dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n",
+                       max8660_addresses[reg], reg_val);
+
+       ret = i2c_smbus_write_byte_data(max8660->client,
+                       max8660_addresses[reg], reg_val);
+       if (ret == 0)
+               max8660->shadow_regs[reg] = reg_val;
+
+       return ret;
+}
+
+
+/*
+ * DCDC functions
+ */
+
+static int max8660_dcdc_is_enabled(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 val = max8660->shadow_regs[MAX8660_OVER1];
+       u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
+       return !!(val & mask);
+}
+
+static int max8660_dcdc_enable(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
+       return max8660_write(max8660, MAX8660_OVER1, 0xff, bit);
+}
+
+static int max8660_dcdc_disable(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4;
+       return max8660_write(max8660, MAX8660_OVER1, mask, 0);
+}
+
+static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector)
+{
+       if (selector > MAX8660_DCDC_MAX_SEL)
+               return -EINVAL;
+       return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
+}
+
+static int max8660_dcdc_get(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
+       u8 selector = max8660->shadow_regs[reg];
+       return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
+}
+
+static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 reg, selector, bits;
+       int ret;
+
+       if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV)
+               return -EINVAL;
+       if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV)
+               return -EINVAL;
+
+       selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1))
+                       / MAX8660_DCDC_STEP;
+
+       ret = max8660_dcdc_list(rdev, selector);
+       if (ret < 0 || ret > max_uV)
+               return -EINVAL;
+
+       reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
+       ret = max8660_write(max8660, reg, 0, selector);
+       if (ret)
+               return ret;
+
+       /* Select target voltage register and activate regulation */
+       bits = (rdev_get_id(rdev) == MAX8660_V3) ? 0x03 : 0x30;
+       return max8660_write(max8660, MAX8660_VCC1, 0xff, bits);
+}
+
+static struct regulator_ops max8660_dcdc_ops = {
+       .is_enabled = max8660_dcdc_is_enabled,
+       .list_voltage = max8660_dcdc_list,
+       .set_voltage = max8660_dcdc_set,
+       .get_voltage = max8660_dcdc_get,
+};
+
+
+/*
+ * LDO5 functions
+ */
+
+static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector)
+{
+       if (selector > MAX8660_LDO5_MAX_SEL)
+               return -EINVAL;
+       return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
+}
+
+static int max8660_ldo5_get(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 selector = max8660->shadow_regs[MAX8660_MDTV2];
+
+       return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
+}
+
+static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 selector;
+       int ret;
+
+       if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV)
+               return -EINVAL;
+       if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV)
+               return -EINVAL;
+
+       selector = (min_uV - (MAX8660_LDO5_MIN_UV - MAX8660_LDO5_STEP + 1))
+                       / MAX8660_LDO5_STEP;
+       ret = max8660_ldo5_list(rdev, selector);
+       if (ret < 0 || ret > max_uV)
+               return -EINVAL;
+
+       ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
+       if (ret)
+               return ret;
+
+       /* Select target voltage register and activate regulation */
+       return max8660_write(max8660, MAX8660_VCC1, 0xff, 0xc0);
+}
+
+static struct regulator_ops max8660_ldo5_ops = {
+       .list_voltage = max8660_ldo5_list,
+       .set_voltage = max8660_ldo5_set,
+       .get_voltage = max8660_ldo5_get,
+};
+
+
+/*
+ * LDO67 functions
+ */
+
+static int max8660_ldo67_is_enabled(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 val = max8660->shadow_regs[MAX8660_OVER2];
+       u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
+       return !!(val & mask);
+}
+
+static int max8660_ldo67_enable(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
+       return max8660_write(max8660, MAX8660_OVER2, 0xff, bit);
+}
+
+static int max8660_ldo67_disable(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4;
+       return max8660_write(max8660, MAX8660_OVER2, mask, 0);
+}
+
+static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector)
+{
+       if (selector > MAX8660_LDO67_MAX_SEL)
+               return -EINVAL;
+       return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
+}
+
+static int max8660_ldo67_get(struct regulator_dev *rdev)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;
+       u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;
+
+       return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
+}
+
+static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+       struct max8660 *max8660 = rdev_get_drvdata(rdev);
+       u8 selector;
+       int ret;
+
+       if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV)
+               return -EINVAL;
+       if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV)
+               return -EINVAL;
+
+       selector = (min_uV - (MAX8660_LDO67_MIN_UV - MAX8660_LDO67_STEP + 1))
+                       / MAX8660_LDO67_STEP;
+
+       ret = max8660_ldo67_list(rdev, selector);
+       if (ret < 0 || ret > max_uV)
+               return -EINVAL;
+
+       if (rdev_get_id(rdev) == MAX8660_V6)
+               return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
+       else
+               return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4);
+}
+
+static struct regulator_ops max8660_ldo67_ops = {
+       .is_enabled = max8660_ldo67_is_enabled,
+       .enable = max8660_ldo67_enable,
+       .disable = max8660_ldo67_disable,
+       .list_voltage = max8660_ldo67_list,
+       .get_voltage = max8660_ldo67_get,
+       .set_voltage = max8660_ldo67_set,
+};
+
+static struct regulator_desc max8660_reg[] = {
+       {
+               .name = "V3(DCDC)",
+               .id = MAX8660_V3,
+               .ops = &max8660_dcdc_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = MAX8660_DCDC_MAX_SEL + 1,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "V4(DCDC)",
+               .id = MAX8660_V4,
+               .ops = &max8660_dcdc_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = MAX8660_DCDC_MAX_SEL + 1,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "V5(LDO)",
+               .id = MAX8660_V5,
+               .ops = &max8660_ldo5_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = MAX8660_LDO5_MAX_SEL + 1,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "V6(LDO)",
+               .id = MAX8660_V6,
+               .ops = &max8660_ldo67_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = MAX8660_LDO67_MAX_SEL + 1,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "V7(LDO)",
+               .id = MAX8660_V7,
+               .ops = &max8660_ldo67_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = MAX8660_LDO67_MAX_SEL + 1,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int max8660_probe(struct i2c_client *client,
+                             const struct i2c_device_id *i2c_id)
+{
+       struct regulator_dev **rdev;
+       struct max8660_platform_data *pdata = client->dev.platform_data;
+       struct max8660 *max8660;
+       int boot_on, i, id, ret = -EINVAL;
+
+       if (pdata->num_subdevs > MAX8660_V_END) {
+               dev_err(&client->dev, "Too much regulators found!\n");
+               goto out;
+       }
+
+       max8660 = kzalloc(sizeof(struct max8660) +
+                       sizeof(struct regulator_dev *) * MAX8660_V_END,
+                       GFP_KERNEL);
+       if (!max8660) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       max8660->client = client;
+       rdev = max8660->rdev;
+
+       if (pdata->en34_is_high) {
+               /* Simulate always on */
+               max8660->shadow_regs[MAX8660_OVER1] = 5;
+       } else {
+               /* Otherwise devices can be toggled via software */
+               max8660_dcdc_ops.enable = max8660_dcdc_enable;
+               max8660_dcdc_ops.disable = max8660_dcdc_disable;
+       }
+
+       /*
+        * First, set up shadow registers to prevent glitches. As some
+        * registers are shared between regulators, everything must be properly
+        * set up for all regulators in advance.
+        */
+       max8660->shadow_regs[MAX8660_ADTV1] =
+               max8660->shadow_regs[MAX8660_ADTV2] =
+               max8660->shadow_regs[MAX8660_SDTV1] =
+               max8660->shadow_regs[MAX8660_SDTV2] = 0x1b;
+       max8660->shadow_regs[MAX8660_MDTV1] =
+               max8660->shadow_regs[MAX8660_MDTV2] = 0x04;
+
+       for (i = 0; i < pdata->num_subdevs; i++) {
+
+               if (!pdata->subdevs[i].platform_data)
+                       goto err_free;
+
+               boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
+
+               switch (pdata->subdevs[i].id) {
+               case MAX8660_V3:
+                       if (boot_on)
+                               max8660->shadow_regs[MAX8660_OVER1] |= 1;
+                       break;
+
+               case MAX8660_V4:
+                       if (boot_on)
+                               max8660->shadow_regs[MAX8660_OVER1] |= 4;
+                       break;
+
+               case MAX8660_V5:
+                       break;
+
+               case MAX8660_V6:
+                       if (boot_on)
+                               max8660->shadow_regs[MAX8660_OVER2] |= 2;
+                       break;
+
+               case MAX8660_V7:
+                       if (!strcmp(i2c_id->name, "max8661")) {
+                               dev_err(&client->dev, "Regulator not on this chip!\n");
+                               goto err_free;
+                       }
+
+                       if (boot_on)
+                               max8660->shadow_regs[MAX8660_OVER2] |= 4;
+                       break;
+
+               default:
+                       dev_err(&client->dev, "invalid regulator %s\n",
+                                pdata->subdevs[i].name);
+                       goto err_free;
+               }
+       }
+
+       /* Finally register devices */
+       for (i = 0; i < pdata->num_subdevs; i++) {
+
+               id = pdata->subdevs[i].id;
+
+               rdev[i] = regulator_register(&max8660_reg[id], &client->dev,
+                                            pdata->subdevs[i].platform_data,
+                                            max8660);
+               if (IS_ERR(rdev[i])) {
+                       ret = PTR_ERR(rdev[i]);
+                       dev_err(&client->dev, "failed to register %s\n",
+                               max8660_reg[id].name);
+                       goto err_unregister;
+               }
+       }
+
+       i2c_set_clientdata(client, rdev);
+       dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n");
+       return 0;
+
+err_unregister:
+       while (--i >= 0)
+               regulator_unregister(rdev[i]);
+err_free:
+       kfree(max8660);
+out:
+       return ret;
+}
+
+static int max8660_remove(struct i2c_client *client)
+{
+       struct regulator_dev **rdev = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < MAX8660_V_END; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+       kfree(rdev);
+       i2c_set_clientdata(client, NULL);
+
+       return 0;
+}
+
+static const struct i2c_device_id max8660_id[] = {
+       { "max8660", 0 },
+       { "max8661", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max8660_id);
+
+static struct i2c_driver max8660_driver = {
+       .probe = max8660_probe,
+       .remove = max8660_remove,
+       .driver         = {
+               .name   = "max8660",
+       },
+       .id_table       = max8660_id,
+};
+
+static int __init max8660_init(void)
+{
+       return i2c_add_driver(&max8660_driver);
+}
+subsys_initcall(max8660_init);
+
+static void __exit max8660_exit(void)
+{
+       i2c_del_driver(&max8660_driver);
+}
+module_exit(max8660_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MAXIM 8660/8661 voltage regulator driver");
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
new file mode 100644 (file)
index 0000000..39c4953
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Regulator Driver for Freescale MC13783 PMIC
+ *
+ * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mfd/mc13783.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#define MC13783_REG_SWITCHERS4                 28
+#define MC13783_REG_SWITCHERS4_PLLEN                   (1 << 18)
+
+#define MC13783_REG_SWITCHERS5                 29
+#define MC13783_REG_SWITCHERS5_SW3EN                   (1 << 20)
+
+#define MC13783_REG_REGULATORMODE0             32
+#define MC13783_REG_REGULATORMODE0_VAUDIOEN            (1 << 0)
+#define MC13783_REG_REGULATORMODE0_VIOHIEN             (1 << 3)
+#define MC13783_REG_REGULATORMODE0_VIOLOEN             (1 << 6)
+#define MC13783_REG_REGULATORMODE0_VDIGEN              (1 << 9)
+#define MC13783_REG_REGULATORMODE0_VGENEN              (1 << 12)
+#define MC13783_REG_REGULATORMODE0_VRFDIGEN            (1 << 15)
+#define MC13783_REG_REGULATORMODE0_VRFREFEN            (1 << 18)
+#define MC13783_REG_REGULATORMODE0_VRFCPEN             (1 << 21)
+
+#define MC13783_REG_REGULATORMODE1             33
+#define MC13783_REG_REGULATORMODE1_VSIMEN              (1 << 0)
+#define MC13783_REG_REGULATORMODE1_VESIMEN             (1 << 3)
+#define MC13783_REG_REGULATORMODE1_VCAMEN              (1 << 6)
+#define MC13783_REG_REGULATORMODE1_VRFBGEN             (1 << 9)
+#define MC13783_REG_REGULATORMODE1_VVIBEN              (1 << 11)
+#define MC13783_REG_REGULATORMODE1_VRF1EN              (1 << 12)
+#define MC13783_REG_REGULATORMODE1_VRF2EN              (1 << 15)
+#define MC13783_REG_REGULATORMODE1_VMMC1EN             (1 << 18)
+#define MC13783_REG_REGULATORMODE1_VMMC2EN             (1 << 21)
+
+#define MC13783_REG_POWERMISC                  34
+#define MC13783_REG_POWERMISC_GPO1EN                   (1 << 6)
+#define MC13783_REG_POWERMISC_GPO2EN                   (1 << 8)
+#define MC13783_REG_POWERMISC_GPO3EN                   (1 << 10)
+#define MC13783_REG_POWERMISC_GPO4EN                   (1 << 12)
+
+struct mc13783_regulator {
+       struct regulator_desc desc;
+       int reg;
+       int enable_bit;
+};
+
+static struct regulator_ops mc13783_regulator_ops;
+
+#define MC13783_DEFINE(prefix, _name, _reg)                            \
+       [MC13783_ ## prefix ## _ ## _name] = {                          \
+               .desc = {                                               \
+                       .name = #prefix "_" #_name,                     \
+                       .ops = &mc13783_regulator_ops,                  \
+                       .type = REGULATOR_VOLTAGE,                      \
+                       .id = MC13783_ ## prefix ## _ ## _name,         \
+                       .owner = THIS_MODULE,                           \
+               },                                                      \
+               .reg = MC13783_REG_ ## _reg,                            \
+               .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
+       }
+
+#define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg)
+#define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg)
+
+static struct mc13783_regulator mc13783_regulators[] = {
+       MC13783_DEFINE_SW(SW3, SWITCHERS5),
+       MC13783_DEFINE_SW(PLL, SWITCHERS4),
+
+       MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VDIG, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VGEN, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0),
+       MC13783_DEFINE_REGU(VSIM, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VESIM, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VCAM, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VVIB, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VRF1, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VRF2, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1),
+       MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1),
+       MC13783_DEFINE_REGU(GPO1, POWERMISC),
+       MC13783_DEFINE_REGU(GPO2, POWERMISC),
+       MC13783_DEFINE_REGU(GPO3, POWERMISC),
+       MC13783_DEFINE_REGU(GPO4, POWERMISC),
+};
+
+struct mc13783_regulator_priv {
+       struct mc13783 *mc13783;
+       struct regulator_dev *regulators[];
+};
+
+static int mc13783_regulator_enable(struct regulator_dev *rdev)
+{
+       struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int ret;
+
+       dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+       mc13783_lock(priv->mc13783);
+       ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
+                       mc13783_regulators[id].enable_bit,
+                       mc13783_regulators[id].enable_bit);
+       mc13783_unlock(priv->mc13783);
+
+       return ret;
+}
+
+static int mc13783_regulator_disable(struct regulator_dev *rdev)
+{
+       struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int ret;
+
+       dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+       mc13783_lock(priv->mc13783);
+       ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
+                       mc13783_regulators[id].enable_bit, 0);
+       mc13783_unlock(priv->mc13783);
+
+       return ret;
+}
+
+static int mc13783_regulator_is_enabled(struct regulator_dev *rdev)
+{
+       struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+       int ret, id = rdev_get_id(rdev);
+       unsigned int val;
+
+       mc13783_lock(priv->mc13783);
+       ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
+       mc13783_unlock(priv->mc13783);
+
+       if (ret)
+               return ret;
+
+       return (val & mc13783_regulators[id].enable_bit) != 0;
+}
+
+static struct regulator_ops mc13783_regulator_ops = {
+       .enable = mc13783_regulator_enable,
+       .disable = mc13783_regulator_disable,
+       .is_enabled = mc13783_regulator_is_enabled,
+};
+
+static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+{
+       struct mc13783_regulator_priv *priv;
+       struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
+       struct mc13783_regulator_platform_data *pdata =
+               dev_get_platdata(&pdev->dev);
+       struct mc13783_regulator_init_data *init_data;
+       int i, ret;
+
+       dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);
+
+       priv = kzalloc(sizeof(*priv) +
+                       pdata->num_regulators * sizeof(priv->regulators[0]),
+                       GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->mc13783 = mc13783;
+
+       for (i = 0; i < pdata->num_regulators; i++) {
+               init_data = &pdata->regulators[i];
+               priv->regulators[i] = regulator_register(
+                               &mc13783_regulators[init_data->id].desc,
+                               &pdev->dev, init_data->init_data, priv);
+
+               if (IS_ERR(priv->regulators[i])) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               mc13783_regulators[i].desc.name);
+                       ret = PTR_ERR(priv->regulators[i]);
+                       goto err;
+               }
+       }
+
+       platform_set_drvdata(pdev, priv);
+
+       return 0;
+err:
+       while (--i >= 0)
+               regulator_unregister(priv->regulators[i]);
+
+       kfree(priv);
+
+       return ret;
+}
+
+static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+{
+       struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev);
+       struct mc13783_regulator_platform_data *pdata =
+               dev_get_platdata(&pdev->dev);
+       int i;
+
+       for (i = 0; i < pdata->num_regulators; i++)
+               regulator_unregister(priv->regulators[i]);
+
+       return 0;
+}
+
+static struct platform_driver mc13783_regulator_driver = {
+       .driver = {
+               .name   = "mc13783-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .remove         = __devexit_p(mc13783_regulator_remove),
+       .probe          = mc13783_regulator_probe,
+};
+
+static int __init mc13783_regulator_init(void)
+{
+       return platform_driver_register(&mc13783_regulator_driver);
+}
+subsys_initcall(mc13783_regulator_init);
+
+static void __exit mc13783_regulator_exit(void)
+{
+       platform_driver_unregister(&mc13783_regulator_driver);
+}
+module_exit(mc13783_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
+MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC");
+MODULE_ALIAS("platform:mc13783-regulator");
diff --git a/drivers/regulator/mc13783.c b/drivers/regulator/mc13783.c
deleted file mode 100644 (file)
index 710211f..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Regulator Driver for Freescale MC13783 PMIC
- *
- * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/mfd/mc13783-private.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/driver.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-struct mc13783_regulator {
-       struct regulator_desc desc;
-       int reg;
-       int enable_bit;
-};
-
-static struct regulator_ops mc13783_regulator_ops;
-
-static struct mc13783_regulator mc13783_regulators[] = {
-       [MC13783_SW_SW3] = {
-               .desc = {
-                       .name   = "SW_SW3",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_SW_SW3,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_SWITCHERS_5,
-               .enable_bit = MC13783_SWCTRL_SW3_EN,
-       },
-       [MC13783_SW_PLL] = {
-               .desc = {
-                       .name   = "SW_PLL",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_SW_PLL,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_SWITCHERS_4,
-               .enable_bit = MC13783_SWCTRL_PLL_EN,
-       },
-       [MC13783_REGU_VAUDIO] = {
-               .desc = {
-                       .name   = "REGU_VAUDIO",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VAUDIO,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VAUDIO_EN,
-       },
-       [MC13783_REGU_VIOHI] = {
-               .desc = {
-                       .name   = "REGU_VIOHI",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VIOHI,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VIOHI_EN,
-       },
-       [MC13783_REGU_VIOLO] = {
-               .desc = {
-                       .name   = "REGU_VIOLO",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VIOLO,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VIOLO_EN,
-       },
-       [MC13783_REGU_VDIG] = {
-               .desc = {
-                       .name   = "REGU_VDIG",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VDIG,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VDIG_EN,
-       },
-       [MC13783_REGU_VGEN] = {
-               .desc = {
-                       .name   = "REGU_VGEN",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VGEN,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VGEN_EN,
-       },
-       [MC13783_REGU_VRFDIG] = {
-               .desc = {
-                       .name   = "REGU_VRFDIG",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRFDIG,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VRFDIG_EN,
-       },
-       [MC13783_REGU_VRFREF] = {
-               .desc = {
-                       .name   = "REGU_VRFREF",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRFREF,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VRFREF_EN,
-       },
-       [MC13783_REGU_VRFCP] = {
-               .desc = {
-                       .name   = "REGU_VRFCP",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRFCP,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_0,
-               .enable_bit = MC13783_REGCTRL_VRFCP_EN,
-       },
-       [MC13783_REGU_VSIM] = {
-               .desc = {
-                       .name   = "REGU_VSIM",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VSIM,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VSIM_EN,
-       },
-       [MC13783_REGU_VESIM] = {
-               .desc = {
-                       .name   = "REGU_VESIM",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VESIM,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VESIM_EN,
-       },
-       [MC13783_REGU_VCAM] = {
-               .desc = {
-                       .name   = "REGU_VCAM",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VCAM,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VCAM_EN,
-       },
-       [MC13783_REGU_VRFBG] = {
-               .desc = {
-                       .name   = "REGU_VRFBG",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRFBG,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VRFBG_EN,
-       },
-       [MC13783_REGU_VVIB] = {
-               .desc = {
-                       .name   = "REGU_VVIB",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VVIB,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VVIB_EN,
-       },
-       [MC13783_REGU_VRF1] = {
-               .desc = {
-                       .name   = "REGU_VRF1",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRF1,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VRF1_EN,
-       },
-       [MC13783_REGU_VRF2] = {
-               .desc = {
-                       .name   = "REGU_VRF2",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VRF2,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VRF2_EN,
-       },
-       [MC13783_REGU_VMMC1] = {
-               .desc = {
-                       .name   = "REGU_VMMC1",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VMMC1,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VMMC1_EN,
-       },
-       [MC13783_REGU_VMMC2] = {
-               .desc = {
-                       .name   = "REGU_VMMC2",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_VMMC2,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_REGULATOR_MODE_1,
-               .enable_bit = MC13783_REGCTRL_VMMC2_EN,
-       },
-       [MC13783_REGU_GPO1] = {
-               .desc = {
-                       .name   = "REGU_GPO1",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_GPO1,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_POWER_MISCELLANEOUS,
-               .enable_bit = MC13783_REGCTRL_GPO1_EN,
-       },
-       [MC13783_REGU_GPO2] = {
-               .desc = {
-                       .name   = "REGU_GPO2",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_GPO2,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_POWER_MISCELLANEOUS,
-               .enable_bit = MC13783_REGCTRL_GPO2_EN,
-       },
-       [MC13783_REGU_GPO3] = {
-               .desc = {
-                       .name   = "REGU_GPO3",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_GPO3,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_POWER_MISCELLANEOUS,
-               .enable_bit = MC13783_REGCTRL_GPO3_EN,
-       },
-       [MC13783_REGU_GPO4] = {
-               .desc = {
-                       .name   = "REGU_GPO4",
-                       .ops    = &mc13783_regulator_ops,
-                       .type   = REGULATOR_VOLTAGE,
-                       .id     = MC13783_REGU_GPO4,
-                       .owner  = THIS_MODULE,
-               },
-               .reg = MC13783_REG_POWER_MISCELLANEOUS,
-               .enable_bit = MC13783_REGCTRL_GPO4_EN,
-       },
-};
-
-struct mc13783_priv {
-       struct regulator_desc desc[ARRAY_SIZE(mc13783_regulators)];
-       struct mc13783 *mc13783;
-       struct regulator_dev *regulators[0];
-};
-
-static int mc13783_enable(struct regulator_dev *rdev)
-{
-       struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-
-       dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
-
-       return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
-                       mc13783_regulators[id].enable_bit,
-                       mc13783_regulators[id].enable_bit);
-}
-
-static int mc13783_disable(struct regulator_dev *rdev)
-{
-       struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-
-       dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
-
-       return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
-                       mc13783_regulators[id].enable_bit, 0);
-}
-
-static int mc13783_is_enabled(struct regulator_dev *rdev)
-{
-       struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-       int ret, id = rdev_get_id(rdev);
-       unsigned int val;
-
-       ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
-       if (ret)
-               return ret;
-
-       return (val & mc13783_regulators[id].enable_bit) != 0;
-}
-
-static struct regulator_ops mc13783_regulator_ops = {
-       .enable         = mc13783_enable,
-       .disable        = mc13783_disable,
-       .is_enabled     = mc13783_is_enabled,
-};
-
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
-{
-       struct mc13783_priv *priv;
-       struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
-       struct mc13783_regulator_init_data *init_data;
-       int i, ret;
-
-       dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);
-
-       priv = kzalloc(sizeof(*priv) + mc13783->num_regulators * sizeof(void *),
-                       GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->mc13783 = mc13783;
-
-       for (i = 0; i < mc13783->num_regulators; i++) {
-               init_data = &mc13783->regulators[i];
-               priv->regulators[i] = regulator_register(
-                               &mc13783_regulators[init_data->id].desc,
-                               &pdev->dev, init_data->init_data, priv);
-
-               if (IS_ERR(priv->regulators[i])) {
-                       dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               mc13783_regulators[i].desc.name);
-                       ret = PTR_ERR(priv->regulators[i]);
-                       goto err;
-               }
-       }
-
-       platform_set_drvdata(pdev, priv);
-
-       return 0;
-err:
-       while (--i >= 0)
-               regulator_unregister(priv->regulators[i]);
-
-       kfree(priv);
-
-       return ret;
-}
-
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
-{
-       struct mc13783_priv *priv = platform_get_drvdata(pdev);
-       struct mc13783 *mc13783 = priv->mc13783;
-       int i;
-
-       for (i = 0; i < mc13783->num_regulators; i++)
-               regulator_unregister(priv->regulators[i]);
-
-       return 0;
-}
-
-static struct platform_driver mc13783_regulator_driver = {
-       .driver = {
-               .name   = "mc13783-regulator",
-               .owner  = THIS_MODULE,
-       },
-       .remove         = __devexit_p(mc13783_regulator_remove),
-};
-
-static int __init mc13783_regulator_init(void)
-{
-       return platform_driver_probe(&mc13783_regulator_driver,
-                       mc13783_regulator_probe);
-}
-subsys_initcall(mc13783_regulator_init);
-
-static void __exit mc13783_regulator_exit(void)
-{
-       platform_driver_unregister(&mc13783_regulator_driver);
-}
-module_exit(mc13783_regulator_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
-MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC");
-MODULE_ALIAS("platform:mc13783-regulator");
index 7ea1c3a..7e67485 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
@@ -40,6 +41,12 @@ struct twlreg_info {
        u8                      table_len;
        const u16               *table;
 
+       /* regulator specific turn-on delay */
+       u16                     delay;
+
+       /* State REMAP default configuration */
+       u8                      remap;
+
        /* chip constraints on regulator behavior */
        u16                     min_mV;
 
@@ -128,6 +135,7 @@ static int twlreg_enable(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        int                     grp;
+       int                     ret;
 
        grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
        if (grp < 0)
@@ -138,7 +146,11 @@ static int twlreg_enable(struct regulator_dev *rdev)
        else
                grp |= P1_GRP_6030;
 
-       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+       ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+
+       udelay(info->delay);
+
+       return ret;
 }
 
 static int twlreg_disable(struct regulator_dev *rdev)
@@ -151,9 +163,9 @@ static int twlreg_disable(struct regulator_dev *rdev)
                return grp;
 
        if (twl_class_is_4030())
-               grp &= ~P1_GRP_4030;
+               grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
        else
-               grp &= ~P1_GRP_6030;
+               grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030);
 
        return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
 }
@@ -294,6 +306,18 @@ static const u16 VSIM_VSEL_table[] = {
 static const u16 VDAC_VSEL_table[] = {
        1200, 1300, 1800, 1800,
 };
+static const u16 VDD1_VSEL_table[] = {
+       800, 1450,
+};
+static const u16 VDD2_VSEL_table[] = {
+       800, 1450, 1500,
+};
+static const u16 VIO_VSEL_table[] = {
+       1800, 1850,
+};
+static const u16 VINTANA2_VSEL_table[] = {
+       2500, 2750,
+};
 static const u16 VAUX1_6030_VSEL_table[] = {
        1000, 1300, 1800, 2500,
        2800, 2900, 3000, 3000,
@@ -414,20 +438,30 @@ static struct regulator_ops twlfixed_ops = {
 
 /*----------------------------------------------------------------------*/
 
-#define TWL4030_ADJUSTABLE_LDO(label, offset, num) \
-               TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030)
-#define TWL4030_FIXED_LDO(label, offset, mVolts, num) \
-               TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030)
-#define TWL6030_ADJUSTABLE_LDO(label, offset, num) \
-               TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, num) \
-               TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030)
-
-#define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \
+#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
+               TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+                       remap_conf, TWL4030)
+#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+                       remap_conf) \
+               TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+                       remap_conf, TWL4030)
+#define TWL6030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+                       remap_conf) \
+               TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+                       remap_conf, TWL6030)
+#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+                       remap_conf) \
+               TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+                       remap_conf, TWL6030)
+
+#define TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf, \
+               family) { \
        .base = offset, \
        .id = num, \
        .table_len = ARRAY_SIZE(label##_VSEL_table), \
        .table = label##_VSEL_table, \
+       .delay = turnon_delay, \
+       .remap = remap_conf, \
        .desc = { \
                .name = #label, \
                .id = family##_REG_##label, \
@@ -438,10 +472,13 @@ static struct regulator_ops twlfixed_ops = {
                }, \
        }
 
-#define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \
+#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
+               family) { \
        .base = offset, \
        .id = num, \
        .min_mV = mVolts, \
+       .delay = turnon_delay, \
+       .remap = remap_conf, \
        .desc = { \
                .name = #label, \
                .id = family##_REG_##label, \
@@ -457,43 +494,41 @@ static struct regulator_ops twlfixed_ops = {
  * software control over them after boot.
  */
 static struct twlreg_info twl_regs[] = {
-       TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
-       TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
-       TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
-       TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
-       TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
-       TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
-       TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
-       /*
-       TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
-       */
-       TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
-       TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9),
-       TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
-       /*
-       TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
-       TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
-       TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
-       TWL4030_SMPS(VIO, 0x4b, 14),
-       TWL4030_SMPS(VDD1, 0x55, 15),
-       TWL4030_SMPS(VDD2, 0x63, 16),
-        */
-       TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
-       TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
-       TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
+       TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00),
+       TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00),
+       TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08),
+       TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08),
+       TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08),
+       TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08),
+       TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08),
+       TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08),
+       TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08),
        /* VUSBCP is managed *only* by the USB subchip */
 
        /* 6030 REG with base as PMC Slave Misc : 0x0030 */
-       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1),
-       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2),
-       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3),
-       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4),
-       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5),
-       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7),
-       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15),
-       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16),
-       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17),
-       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18)
+       /* Turnon-delay and remap configuration values for 6030 are not
+          verified since the specification is not public */
+       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x08),
+       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x08),
+       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x08),
+       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x08),
+       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x08),
+       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x08),
+       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x08),
+       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x08),
+       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x08),
+       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x08)
 };
 
 static int twlreg_probe(struct platform_device *pdev)
@@ -525,6 +560,19 @@ static int twlreg_probe(struct platform_device *pdev)
        c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
                                | REGULATOR_CHANGE_MODE
                                | REGULATOR_CHANGE_STATUS;
+       switch (pdev->id) {
+       case TWL4030_REG_VIO:
+       case TWL4030_REG_VDD1:
+       case TWL4030_REG_VDD2:
+       case TWL4030_REG_VPLL1:
+       case TWL4030_REG_VINTANA1:
+       case TWL4030_REG_VINTANA2:
+       case TWL4030_REG_VINTDIG:
+               c->always_on = true;
+               break;
+       default:
+               break;
+       }
 
        rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
        if (IS_ERR(rdev)) {
@@ -534,6 +582,9 @@ static int twlreg_probe(struct platform_device *pdev)
        }
        platform_set_drvdata(pdev, rdev);
 
+       twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
+                                               info->remap);
+
        /* NOTE:  many regulators support short-circuit IRQs (presentable
         * as REGULATOR_OVER_CURRENT notifications?) configured via:
         *  - SC_CONFIG
index 2eefc1a..0a65775 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/regulator.h>
@@ -39,6 +41,7 @@
 #define WM831X_DCDC_CONTROL_2     1
 #define WM831X_DCDC_ON_CONFIG     2
 #define WM831X_DCDC_SLEEP_CONTROL 3
+#define WM831X_DCDC_DVS_CONTROL   4
 
 /*
  * Shared
@@ -50,6 +53,10 @@ struct wm831x_dcdc {
        int base;
        struct wm831x *wm831x;
        struct regulator_dev *regulator;
+       int dvs_gpio;
+       int dvs_gpio_state;
+       int on_vsel;
+       int dvs_vsel;
 };
 
 static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev)
@@ -240,11 +247,9 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_buckv_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                        int min_uV, int max_uV)
+static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
+                                          int min_uV, int max_uV)
 {
-       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = dcdc->wm831x;
        u16 vsel;
 
        if (min_uV < 600000)
@@ -257,39 +262,126 @@ static int wm831x_buckv_set_voltage_int(struct regulator_dev *rdev, int reg,
        if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV)
                return -EINVAL;
 
-       return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_VSEL_MASK, vsel);
+       return vsel;
+}
+
+static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev,
+                                          int min_uV, int max_uV)
+{
+       u16 vsel;
+
+       if (max_uV < 600000 || max_uV > 1800000)
+               return -EINVAL;
+
+       vsel = ((max_uV - 600000) / 12500) + 8;
+
+       if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV ||
+           wm831x_buckv_list_voltage(rdev, vsel) < max_uV)
+               return -EINVAL;
+
+       return vsel;
+}
+
+static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
+{
+       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+
+       if (state == dcdc->dvs_gpio_state)
+               return 0;
+
+       dcdc->dvs_gpio_state = state;
+       gpio_set_value(dcdc->dvs_gpio, state);
+
+       /* Should wait for DVS state change to be asserted if we have
+        * a GPIO for it, for now assume the device is configured
+        * for the fastest possible transition.
+        */
+
+       return 0;
 }
 
 static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
-                                    int min_uV, int max_uV)
+                                   int min_uV, int max_uV)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-       u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+       struct wm831x *wm831x = dcdc->wm831x;
+       int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+       int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
+       int vsel, ret;
+
+       vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV);
+       if (vsel < 0)
+               return vsel;
+
+       /* If this value is already set then do a GPIO update if we can */
+       if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
+               return wm831x_buckv_set_dvs(rdev, 0);
+
+       if (dcdc->dvs_gpio && dcdc->dvs_vsel == vsel)
+               return wm831x_buckv_set_dvs(rdev, 1);
+
+       /* Always set the ON status to the minimum voltage */
+       ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel);
+       if (ret < 0)
+               return ret;
+       dcdc->on_vsel = vsel;
+
+       if (!dcdc->dvs_gpio)
+               return ret;
+
+       /* Kick the voltage transition now */
+       ret = wm831x_buckv_set_dvs(rdev, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Set the high voltage as the DVS voltage.  This is optimised
+        * for CPUfreq usage, most processors will keep the maximum
+        * voltage constant and lower the minimum with the frequency. */
+       vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV);
+       if (vsel < 0) {
+               /* This should never happen - at worst the same vsel
+                * should be chosen */
+               WARN_ON(vsel < 0);
+               return 0;
+       }
+
+       /* Don't bother if it's the same VSEL we're already using */
+       if (vsel == dcdc->on_vsel)
+               return 0;
 
-       return wm831x_buckv_set_voltage_int(rdev, reg, min_uV, max_uV);
+       ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel);
+       if (ret == 0)
+               dcdc->dvs_vsel = vsel;
+       else
+               dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n",
+                        ret);
+
+       return 0;
 }
 
 static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
-                                            int uV)
+                                           int uV)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+       struct wm831x *wm831x = dcdc->wm831x;
        u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
+       int vsel;
+
+       vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV);
+       if (vsel < 0)
+               return vsel;
 
-       return wm831x_buckv_set_voltage_int(rdev, reg, uV, uV);
+       return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);
 }
 
 static int wm831x_buckv_get_voltage(struct regulator_dev *rdev)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = dcdc->wm831x;
-       u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
-       int val;
 
-       val = wm831x_reg_read(wm831x, reg);
-       if (val < 0)
-               return val;
-
-       return wm831x_buckv_list_voltage(rdev, val & WM831X_DC1_ON_VSEL_MASK);
+       if (dcdc->dvs_gpio && dcdc->dvs_gpio_state)
+               return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel);
+       else
+               return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel);
 }
 
 /* Current limit options */
@@ -346,6 +438,64 @@ static struct regulator_ops wm831x_buckv_ops = {
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
+/*
+ * Set up DVS control.  We just log errors since we can still run
+ * (with reduced performance) if we fail.
+ */
+static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+                                           struct wm831x_buckv_pdata *pdata)
+{
+       struct wm831x *wm831x = dcdc->wm831x;
+       int ret;
+       u16 ctrl;
+
+       if (!pdata || !pdata->dvs_gpio)
+               return;
+
+       switch (pdata->dvs_control_src) {
+       case 1:
+               ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       case 2:
+               ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       default:
+               dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
+                       pdata->dvs_control_src, dcdc->name);
+               return;
+       }
+
+       ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
+                             WM831X_DC1_DVS_SRC_MASK, ctrl);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
+                       dcdc->name, ret);
+               return;
+       }
+
+       ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
+                       dcdc->name, ret);
+               return;
+       }
+
+       /* gpiolib won't let us read the GPIO status so pick the higher
+        * of the two existing voltages so we take it as platform data.
+        */
+       dcdc->dvs_gpio_state = pdata->dvs_init_state;
+
+       ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n",
+                       dcdc->name, ret);
+               gpio_free(pdata->dvs_gpio);
+               return;
+       }
+
+       dcdc->dvs_gpio = pdata->dvs_gpio;
+}
+
 static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -384,6 +534,23 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        dcdc->desc.ops = &wm831x_buckv_ops;
        dcdc->desc.owner = THIS_MODULE;
 
+       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret);
+               goto err;
+       }
+       dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
+
+       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
+               goto err;
+       }
+       dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
+
+       if (pdata->dcdc[id])
+               wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+
        dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
                                             pdata->dcdc[id], dcdc);
        if (IS_ERR(dcdc->regulator)) {
@@ -422,6 +589,8 @@ err_uv:
 err_regulator:
        regulator_unregister(dcdc->regulator);
 err:
+       if (dcdc->dvs_gpio)
+               gpio_free(dcdc->dvs_gpio);
        kfree(dcdc);
        return ret;
 }
@@ -434,6 +603,8 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
        wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
        wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
        regulator_unregister(dcdc->regulator);
+       if (dcdc->dvs_gpio)
+               gpio_free(dcdc->dvs_gpio);
        kfree(dcdc);
 
        return 0;
index 902db56..61e02ac 100644 (file)
@@ -470,7 +470,7 @@ static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = ldo->wm831x;
        int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
-       unsigned int ret;
+       int ret;
 
        ret = wm831x_reg_read(wm831x, on_reg);
        if (ret < 0)
index eb154dc..c8c1232 100644 (file)
@@ -686,7 +686,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
         */
 #if    defined(CONFIG_ATARI)
        address_space = 64;
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__)
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \
+                       || defined(__sparc__) || defined(__mips__)
        address_space = 128;
 #else
 #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
index 259db7f..9630e7d 100644 (file)
@@ -778,6 +778,8 @@ static int __devinit ds1305_probe(struct spi_device *spi)
                                        spi->irq, status);
                        goto fail1;
                }
+
+               device_set_wakeup_capable(&spi->dev, 1);
        }
 
        /* export NVRAM */
index 8a99da6..c4ec5c1 100644 (file)
@@ -881,6 +881,8 @@ read_rtc:
                                "unable to request IRQ!\n");
                        goto exit_irq;
                }
+
+               device_set_wakeup_capable(&client->dev, 1);
                set_bit(HAS_ALARM, &ds1307->flags);
                dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
        }
index 713f7bf..5317bbc 100644 (file)
@@ -383,6 +383,8 @@ static int ds1374_probe(struct i2c_client *client,
                        dev_err(&client->dev, "unable to request IRQ\n");
                        goto out_free;
                }
+
+               device_set_wakeup_capable(&client->dev, 1);
        }
 
        ds1374->rtc = rtc_device_register(client->name, &client->dev,
index 3bf7592..84d3bba 100644 (file)
@@ -76,6 +76,7 @@
                  Fix bug in twa_get_param() on 4GB+.
                  Use pci_resource_len() for ioremap().
    2.26.02.012 - Add power management support.
+   2.26.02.013 - Fix bug in twa_load_sgl().
 */
 
 #include <linux/module.h>
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.012"
+#define TW_DRIVER_VERSION "2.26.02.013"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -1382,10 +1383,12 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
                newcommand = &full_command_packet->command.newcommand;
                newcommand->request_id__lunl =
                        cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
-               newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
-               newcommand->sg_list[0].length = cpu_to_le32(length);
+               if (length) {
+                       newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
+                       newcommand->sg_list[0].length = cpu_to_le32(length);
+               }
                newcommand->sgl_entries__lunh =
-                       cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
+                       cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), length ? 1 : 0));
        } else {
                oldcommand = &full_command_packet->command.oldcommand;
                oldcommand->request_id = request_id;
index 36900c7..9191d1e 100644 (file)
@@ -388,6 +388,16 @@ config BLK_DEV_3W_XXXX_RAID
          Please read the comments at the top of
          <file:drivers/scsi/3w-xxxx.c>.
 
+config SCSI_HPSA
+       tristate "HP Smart Array SCSI driver"
+       depends on PCI && SCSI
+       help
+         This driver supports HP Smart Array Controllers (circa 2009).
+         It is a SCSI alternative to the cciss driver, which is a block
+         driver.  Anyone wishing to use HP Smart Array controllers who
+         would prefer the devices be presented to linux as SCSI devices,
+         rather than as generic block devices should say Y here.
+
 config SCSI_3W_9XXX
        tristate "3ware 9xxx SATA-RAID support"
        depends on PCI && SCSI
index 280d3c6..92a8c50 100644 (file)
@@ -91,6 +91,7 @@ obj-$(CONFIG_SCSI_BFA_FC)     += bfa/
 obj-$(CONFIG_SCSI_PAS16)       += pas16.o
 obj-$(CONFIG_SCSI_T128)                += t128.o
 obj-$(CONFIG_SCSI_DMX3191D)    += dmx3191d.o
+obj-$(CONFIG_SCSI_HPSA)                += hpsa.o
 obj-$(CONFIG_SCSI_DTC3280)     += dtc.o
 obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
 obj-$(CONFIG_SCSI_ZALON)       += zalon7xx.o
index 698a527..f008708 100644 (file)
@@ -135,11 +135,15 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
        while ((compl = be_mcc_compl_get(phba))) {
                if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
                        /* Interpret flags as an async trailer */
-                       BUG_ON(!is_link_state_evt(compl->flags));
+                       if (is_link_state_evt(compl->flags))
+                               /* Interpret compl as a async link evt */
+                               beiscsi_async_link_state_process(phba,
+                                  (struct be_async_event_link_state *) compl);
+                       else
+                               SE_DEBUG(DBG_LVL_1,
+                                        " Unsupported Async Event, flags"
+                                        " = 0x%08x \n", compl->flags);
 
-                       /* Interpret compl as a async link evt */
-                       beiscsi_async_link_state_process(phba,
-                               (struct be_async_event_link_state *) compl);
                } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
                                status = be_mcc_compl_process(ctrl, compl);
                                atomic_dec(&phba->ctrl.mcc_obj.q.used);
index 2b973f3..6cf9dc3 100644 (file)
@@ -684,6 +684,7 @@ extern unsigned int error_mask1, error_mask2;
 extern u64 iscsi_error_mask;
 extern unsigned int en_tcp_dack;
 extern unsigned int event_coal_div;
+extern unsigned int event_coal_min;
 
 extern struct scsi_transport_template *bnx2i_scsi_xport_template;
 extern struct iscsi_transport bnx2i_iscsi_transport;
index 5c8d763..1af578d 100644 (file)
@@ -133,20 +133,38 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
 {
        struct bnx2i_5771x_cq_db *cq_db;
        u16 cq_index;
+       u16 next_index;
+       u32 num_active_cmds;
 
+
+       /* Coalesce CQ entries only on 10G devices */
        if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
                return;
 
+       /* Do not update CQ DB multiple times before firmware writes
+        * '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
+        * interrupts and other unwanted results
+        */
+       cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt;
+       if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
+               return;
+
        if (action == CNIC_ARM_CQE) {
-               cq_index = ep->qp.cqe_exp_seq_sn +
-                          ep->num_active_cmds / event_coal_div;
-               cq_index %= (ep->qp.cqe_size * 2 + 1);
-               if (!cq_index) {
+               num_active_cmds = ep->num_active_cmds;
+               if (num_active_cmds <= event_coal_min)
+                       next_index = 1;
+               else
+                       next_index = event_coal_min +
+                               (num_active_cmds - event_coal_min) / event_coal_div;
+               if (!next_index)
+                       next_index = 1;
+               cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
+               if (cq_index > ep->qp.cqe_size * 2)
+                       cq_index -= ep->qp.cqe_size * 2;
+               if (!cq_index)
                        cq_index = 1;
-                       cq_db = (struct bnx2i_5771x_cq_db *)
-                                       ep->qp.cq_pgtbl_virt;
-                       cq_db->sqn[0] = cq_index;
-               }
+
+               cq_db->sqn[0] = cq_index;
        }
 }
 
@@ -366,6 +384,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
        struct bnx2i_cmd *bnx2i_cmd;
        struct bnx2i_tmf_request *tmfabort_wqe;
        u32 dword;
+       u32 scsi_lun[2];
 
        bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
        tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -376,27 +395,35 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
        tmfabort_wqe->op_attr = 0;
        tmfabort_wqe->op_attr =
                ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK;
-       tmfabort_wqe->lun[0] = be32_to_cpu(tmfabort_hdr->lun[0]);
-       tmfabort_wqe->lun[1] = be32_to_cpu(tmfabort_hdr->lun[1]);
 
        tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14));
        tmfabort_wqe->reserved2 = 0;
        tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn);
 
        ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
-       if (!ctask || ctask->sc)
+       if (!ctask || !ctask->sc)
                /*
                 * the iscsi layer must have completed the cmd while this
                 * was starting up.
+                *
+                * Note: In the case of a SCSI cmd timeout, the task's sc
+                *       is still active; hence ctask->sc != 0
+                *       In this case, the task must be aborted
                 */
                return 0;
+
        ref_sc = ctask->sc;
 
+       /* Retrieve LUN directly from the ref_sc */
+       int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun);
+       tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
+       tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
+
        if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
                dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
        else
                dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-       tmfabort_wqe->ref_itt = (dword | tmfabort_hdr->rtt);
+       tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
        tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
 
        tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
index 0c4210d..6d8172e 100644 (file)
@@ -17,8 +17,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME                "bnx2i"
-#define DRV_MODULE_VERSION     "2.0.1e"
-#define DRV_MODULE_RELDATE     "June 22, 2009"
+#define DRV_MODULE_VERSION     "2.1.0"
+#define DRV_MODULE_RELDATE     "Dec 06, 2009"
 
 static char version[] __devinitdata =
                "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -32,6 +32,10 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 
 static DEFINE_MUTEX(bnx2i_dev_lock);
 
+unsigned int event_coal_min = 24;
+module_param(event_coal_min, int, 0664);
+MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
+
 unsigned int event_coal_div = 1;
 module_param(event_coal_div, int, 0664);
 MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
@@ -83,8 +87,12 @@ void bnx2i_identify_device(struct bnx2i_hba *hba)
                set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
                hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
        } else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
-                  hba->pci_did == PCI_DEVICE_ID_NX2_57711)
+                  hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
+                  hba->pci_did == PCI_DEVICE_ID_NX2_57711E)
                set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
+       else
+               printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
+                                 hba->pci_did);
 }
 
 
@@ -363,7 +371,7 @@ static int __init bnx2i_mod_init(void)
 
        printk(KERN_INFO "%s", version);
 
-       if (!is_power_of_2(sq_size))
+       if (sq_size && !is_power_of_2(sq_size))
                sq_size = roundup_pow_of_two(sq_size);
 
        mutex_init(&bnx2i_dev_lock);
index 132898c..33b2294 100644 (file)
@@ -485,7 +485,6 @@ static int bnx2i_setup_cmd_pool(struct bnx2i_hba *hba,
                struct iscsi_task *task = session->cmds[i];
                struct bnx2i_cmd *cmd = task->dd_data;
 
-               /* Anil */
                task->hdr = &cmd->hdr;
                task->hdr_max = sizeof(struct iscsi_hdr);
 
@@ -765,7 +764,6 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
        hba->pci_svid = hba->pcidev->subsystem_vendor;
        hba->pci_func = PCI_FUNC(hba->pcidev->devfn);
        hba->pci_devno = PCI_SLOT(hba->pcidev->devfn);
-       bnx2i_identify_device(hba);
 
        bnx2i_identify_device(hba);
        bnx2i_setup_host_queue_size(hba, shost);
index c1d5be4..26ffdcd 100644 (file)
@@ -291,7 +291,7 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
        c3cn_hold(c3cn);
        spin_lock_bh(&c3cn->lock);
        if (c3cn->state == C3CN_STATE_CONNECTING)
-               fail_act_open(c3cn, EHOSTUNREACH);
+               fail_act_open(c3cn, -EHOSTUNREACH);
        spin_unlock_bh(&c3cn->lock);
        c3cn_put(c3cn);
        __kfree_skb(skb);
@@ -792,18 +792,18 @@ static int act_open_rpl_status_to_errno(int status)
 {
        switch (status) {
        case CPL_ERR_CONN_RESET:
-               return ECONNREFUSED;
+               return -ECONNREFUSED;
        case CPL_ERR_ARP_MISS:
-               return EHOSTUNREACH;
+               return -EHOSTUNREACH;
        case CPL_ERR_CONN_TIMEDOUT:
-               return ETIMEDOUT;
+               return -ETIMEDOUT;
        case CPL_ERR_TCAM_FULL:
-               return ENOMEM;
+               return -ENOMEM;
        case CPL_ERR_CONN_EXIST:
                cxgb3i_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
-               return EADDRINUSE;
+               return -EADDRINUSE;
        default:
-               return EIO;
+               return -EIO;
        }
 }
 
@@ -817,7 +817,7 @@ static void act_open_retry_timer(unsigned long data)
        spin_lock_bh(&c3cn->lock);
        skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
        if (!skb)
-               fail_act_open(c3cn, ENOMEM);
+               fail_act_open(c3cn, -ENOMEM);
        else {
                skb->sk = (struct sock *)c3cn;
                set_arp_failure_handler(skb, act_open_req_arp_failure);
@@ -966,14 +966,14 @@ static int abort_status_to_errno(struct s3_conn *c3cn, int abort_reason,
        case CPL_ERR_BAD_SYN: /* fall through */
        case CPL_ERR_CONN_RESET:
                return c3cn->state > C3CN_STATE_ESTABLISHED ?
-                       EPIPE : ECONNRESET;
+                       -EPIPE : -ECONNRESET;
        case CPL_ERR_XMIT_TIMEDOUT:
        case CPL_ERR_PERSIST_TIMEDOUT:
        case CPL_ERR_FINWAIT2_TIMEDOUT:
        case CPL_ERR_KEEPALIVE_TIMEDOUT:
-               return ETIMEDOUT;
+               return -ETIMEDOUT;
        default:
-               return EIO;
+               return -EIO;
        }
 }
 
@@ -1563,7 +1563,7 @@ free_tid:
        s3_free_atid(cdev, c3cn->tid);
        c3cn->tid = 0;
 out_err:
-       return -1;
+       return -EINVAL;
 }
 
 
index 7091050..1fe3b0f 100644 (file)
@@ -388,8 +388,8 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
        if (err > 0) {
                int pdulen = err;
 
-       cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
-                       task, skb, skb->len, skb->data_len, err);
+               cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+                               task, skb, skb->len, skb->data_len, err);
 
                if (task->conn->hdrdgst_en)
                        pdulen += ISCSI_DIGEST_SIZE;
index 47cfe1c..1a66019 100644 (file)
@@ -748,6 +748,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
        {"IBM", "1724"},
        {"IBM", "1726"},
        {"IBM", "1742"},
+       {"IBM", "1745"},
+       {"IBM", "1746"},
        {"IBM", "1814"},
        {"IBM", "1815"},
        {"IBM", "1818"},
index a30ffaa..10be9f3 100644 (file)
@@ -101,6 +101,8 @@ static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
 
 static int fcoe_create(const char *, struct kernel_param *);
 static int fcoe_destroy(const char *, struct kernel_param *);
+static int fcoe_enable(const char *, struct kernel_param *);
+static int fcoe_disable(const char *, struct kernel_param *);
 
 static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
                                      u32 did, struct fc_frame *,
@@ -115,10 +117,16 @@ static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
 
 module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in.");
+MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
 module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe");
+MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
+module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(enable, "string");
+MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
+module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(disable, "string");
+MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
 
 /* notification function for packets from net device */
 static struct notifier_block fcoe_notifier = {
@@ -545,6 +553,23 @@ static void fcoe_queue_timer(ulong lport)
 }
 
 /**
+ * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
+ * @netdev: the associated net device
+ * @wwn: the output WWN
+ * @type: the type of WWN (WWPN or WWNN)
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
+{
+       const struct net_device_ops *ops = netdev->netdev_ops;
+
+       if (ops->ndo_fcoe_get_wwn)
+               return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
+       return -EINVAL;
+}
+
+/**
  * fcoe_netdev_config() - Set up net devive for SW FCoE
  * @lport:  The local port that is associated with the net device
  * @netdev: The associated net device
@@ -611,9 +636,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
                 */
                if (netdev->priv_flags & IFF_802_1Q_VLAN)
                        vid = vlan_dev_vlan_id(netdev);
-               wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
+
+               if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
+                       wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
                fc_set_wwnn(lport, wwnn);
-               wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, vid);
+               if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
+                       wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr,
+                                                2, vid);
                fc_set_wwpn(lport, wwpn);
        }
 
@@ -1231,7 +1260,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
                                "CPU.\n");
 
                spin_unlock_bh(&fps->fcoe_rx_list.lock);
-               cpu = first_cpu(cpu_online_map);
+               cpu = cpumask_first(cpu_online_mask);
                fps = &per_cpu(fcoe_percpu, cpu);
                spin_lock_bh(&fps->fcoe_rx_list.lock);
                if (!fps->thread) {
@@ -1838,6 +1867,104 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer)
 }
 
 /**
+ * fcoe_disable() - Disables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be disabled
+ * @kp:            The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_disable(const char *buffer, struct kernel_param *kp)
+{
+       struct fcoe_interface *fcoe;
+       struct net_device *netdev;
+       int rc = 0;
+
+       mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+       /*
+        * Make sure the module has been initialized, and is not about to be
+        * removed.  Module paramter sysfs files are writable before the
+        * module_init function is called and after module_exit.
+        */
+       if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+#endif
+
+       netdev = fcoe_if_to_netdev(buffer);
+       if (!netdev) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+
+       rtnl_lock();
+       fcoe = fcoe_hostlist_lookup_port(netdev);
+       rtnl_unlock();
+
+       if (fcoe)
+               fc_fabric_logoff(fcoe->ctlr.lp);
+       else
+               rc = -ENODEV;
+
+       dev_put(netdev);
+out_nodev:
+       mutex_unlock(&fcoe_config_mutex);
+       return rc;
+}
+
+/**
+ * fcoe_enable() - Enables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be enabled
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_enable(const char *buffer, struct kernel_param *kp)
+{
+       struct fcoe_interface *fcoe;
+       struct net_device *netdev;
+       int rc = 0;
+
+       mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+       /*
+        * Make sure the module has been initialized, and is not about to be
+        * removed.  Module paramter sysfs files are writable before the
+        * module_init function is called and after module_exit.
+        */
+       if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+#endif
+
+       netdev = fcoe_if_to_netdev(buffer);
+       if (!netdev) {
+               rc = -ENODEV;
+               goto out_nodev;
+       }
+
+       rtnl_lock();
+       fcoe = fcoe_hostlist_lookup_port(netdev);
+       rtnl_unlock();
+
+       if (fcoe)
+               rc = fc_fabric_login(fcoe->ctlr.lp);
+       else
+               rc = -ENODEV;
+
+       dev_put(netdev);
+out_nodev:
+       mutex_unlock(&fcoe_config_mutex);
+       return rc;
+}
+
+/**
  * fcoe_destroy() - Destroy a FCoE interface
  * @buffer: The name of the Ethernet interface to be destroyed
  * @kp:            The associated kernel parameter
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
new file mode 100644 (file)
index 0000000..bb96fdd
--- /dev/null
@@ -0,0 +1,3531 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; version 2 of the License.
+ *
+ *    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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/compat.h>
+#include <linux/blktrace_api.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <linux/cciss_ioctl.h>
+#include <linux/string.h>
+#include <linux/bitmap.h>
+#include <asm/atomic.h>
+#include <linux/kthread.h>
+#include "hpsa_cmd.h"
+#include "hpsa.h"
+
+/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */
+#define HPSA_DRIVER_VERSION "1.0.0"
+#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
+
+/* How long to wait (in milliseconds) for board to go into simple mode */
+#define MAX_CONFIG_WAIT 30000
+#define MAX_IOCTL_CONFIG_WAIT 1000
+
+/*define how many times we will try a command because of bus resets */
+#define MAX_CMD_RETRIES 3
+
+/* Embedded module documentation macros - see modules.h */
+MODULE_AUTHOR("Hewlett-Packard Company");
+MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \
+       HPSA_DRIVER_VERSION);
+MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
+MODULE_VERSION(HPSA_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+static int hpsa_allow_any;
+module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hpsa_allow_any,
+               "Allow hpsa driver to access unknown HP Smart Array hardware");
+
+/* define the PCI info for the cards we can control */
+static const struct pci_device_id hpsa_pci_device_id[] = {
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3223},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3234},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x323D},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3241},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3243},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3245},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3247},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324a},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324b},
+       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
+               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id);
+
+/*  board_id = Subsystem Device ID & Vendor ID
+ *  product = Marketing Name for the board
+ *  access = Address of the struct of function pointers
+ */
+static struct board_type products[] = {
+       {0x3223103C, "Smart Array P800", &SA5_access},
+       {0x3234103C, "Smart Array P400", &SA5_access},
+       {0x323d103c, "Smart Array P700M", &SA5_access},
+       {0x3241103C, "Smart Array P212", &SA5_access},
+       {0x3243103C, "Smart Array P410", &SA5_access},
+       {0x3245103C, "Smart Array P410i", &SA5_access},
+       {0x3247103C, "Smart Array P411", &SA5_access},
+       {0x3249103C, "Smart Array P812", &SA5_access},
+       {0x324a103C, "Smart Array P712m", &SA5_access},
+       {0x324b103C, "Smart Array P711m", &SA5_access},
+       {0xFFFF103C, "Unknown Smart Array", &SA5_access},
+};
+
+static int number_of_controllers;
+
+static irqreturn_t do_hpsa_intr(int irq, void *dev_id);
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static void start_io(struct ctlr_info *h);
+
+#ifdef CONFIG_COMPAT
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg);
+#endif
+
+static void cmd_free(struct ctlr_info *h, struct CommandList *c);
+static void cmd_special_free(struct ctlr_info *h, struct CommandList *c);
+static struct CommandList *cmd_alloc(struct ctlr_info *h);
+static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
+static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
+       void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+       int cmd_type);
+
+static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
+               void (*done)(struct scsi_cmnd *));
+
+static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
+static int hpsa_slave_alloc(struct scsi_device *sdev);
+static void hpsa_slave_destroy(struct scsi_device *sdev);
+
+static ssize_t raid_level_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t lunid_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static ssize_t unique_id_show(struct device *dev,
+       struct device_attribute *attr, char *buf);
+static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
+static ssize_t host_store_rescan(struct device *dev,
+        struct device_attribute *attr, const char *buf, size_t count);
+static int check_for_unit_attention(struct ctlr_info *h,
+       struct CommandList *c);
+static void check_ioctl_unit_attention(struct ctlr_info *h,
+       struct CommandList *c);
+
+static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
+static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
+
+static struct device_attribute *hpsa_sdev_attrs[] = {
+       &dev_attr_raid_level,
+       &dev_attr_lunid,
+       &dev_attr_unique_id,
+       NULL,
+};
+
+static struct device_attribute *hpsa_shost_attrs[] = {
+       &dev_attr_rescan,
+       NULL,
+};
+
+static struct scsi_host_template hpsa_driver_template = {
+       .module                 = THIS_MODULE,
+       .name                   = "hpsa",
+       .proc_name              = "hpsa",
+       .queuecommand           = hpsa_scsi_queue_command,
+       .can_queue              = 512,
+       .this_id                = -1,
+       .sg_tablesize           = MAXSGENTRIES,
+       .cmd_per_lun            = 512,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .eh_device_reset_handler = hpsa_eh_device_reset_handler,
+       .ioctl                  = hpsa_ioctl,
+       .slave_alloc            = hpsa_slave_alloc,
+       .slave_destroy          = hpsa_slave_destroy,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl           = hpsa_compat_ioctl,
+#endif
+       .sdev_attrs = hpsa_sdev_attrs,
+       .shost_attrs = hpsa_shost_attrs,
+};
+
+static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
+{
+       unsigned long *priv = shost_priv(sdev->host);
+       return (struct ctlr_info *) *priv;
+}
+
+static struct task_struct *hpsa_scan_thread;
+static DEFINE_MUTEX(hpsa_scan_mutex);
+static LIST_HEAD(hpsa_scan_q);
+static int hpsa_scan_func(void *data);
+
+/**
+ * add_to_scan_list() - add controller to rescan queue
+ * @h:               Pointer to the controller.
+ *
+ * Adds the controller to the rescan queue if not already on the queue.
+ *
+ * returns 1 if added to the queue, 0 if skipped (could be on the
+ * queue already, or the controller could be initializing or shutting
+ * down).
+ **/
+static int add_to_scan_list(struct ctlr_info *h)
+{
+       struct ctlr_info *test_h;
+       int found = 0;
+       int ret = 0;
+
+       if (h->busy_initializing)
+               return 0;
+
+       /*
+        * If we don't get the lock, it means the driver is unloading
+        * and there's no point in scheduling a new scan.
+        */
+       if (!mutex_trylock(&h->busy_shutting_down))
+               return 0;
+
+       mutex_lock(&hpsa_scan_mutex);
+       list_for_each_entry(test_h, &hpsa_scan_q, scan_list) {
+               if (test_h == h) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found && !h->busy_scanning) {
+               INIT_COMPLETION(h->scan_wait);
+               list_add_tail(&h->scan_list, &hpsa_scan_q);
+               ret = 1;
+       }
+       mutex_unlock(&hpsa_scan_mutex);
+       mutex_unlock(&h->busy_shutting_down);
+
+       return ret;
+}
+
+/**
+ * remove_from_scan_list() - remove controller from rescan queue
+ * @h:                    Pointer to the controller.
+ *
+ * Removes the controller from the rescan queue if present. Blocks if
+ * the controller is currently conducting a rescan.  The controller
+ * can be in one of three states:
+ * 1. Doesn't need a scan
+ * 2. On the scan list, but not scanning yet (we remove it)
+ * 3. Busy scanning (and not on the list). In this case we want to wait for
+ *    the scan to complete to make sure the scanning thread for this
+ *    controller is completely idle.
+ **/
+static void remove_from_scan_list(struct ctlr_info *h)
+{
+       struct ctlr_info *test_h, *tmp_h;
+
+       mutex_lock(&hpsa_scan_mutex);
+       list_for_each_entry_safe(test_h, tmp_h, &hpsa_scan_q, scan_list) {
+               if (test_h == h) { /* state 2. */
+                       list_del(&h->scan_list);
+                       complete_all(&h->scan_wait);
+                       mutex_unlock(&hpsa_scan_mutex);
+                       return;
+               }
+       }
+       if (h->busy_scanning) { /* state 3. */
+               mutex_unlock(&hpsa_scan_mutex);
+               wait_for_completion(&h->scan_wait);
+       } else { /* state 1, nothing to do. */
+               mutex_unlock(&hpsa_scan_mutex);
+       }
+}
+
+/* hpsa_scan_func() - kernel thread used to rescan controllers
+ * @data:       Ignored.
+ *
+ * A kernel thread used scan for drive topology changes on
+ * controllers. The thread processes only one controller at a time
+ * using a queue.  Controllers are added to the queue using
+ * add_to_scan_list() and removed from the queue either after done
+ * processing or using remove_from_scan_list().
+ *
+ * returns 0.
+ **/
+static int hpsa_scan_func(__attribute__((unused)) void *data)
+{
+       struct ctlr_info *h;
+       int host_no;
+
+       while (1) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+               if (kthread_should_stop())
+                       break;
+
+               while (1) {
+                       mutex_lock(&hpsa_scan_mutex);
+                       if (list_empty(&hpsa_scan_q)) {
+                               mutex_unlock(&hpsa_scan_mutex);
+                               break;
+                       }
+                       h = list_entry(hpsa_scan_q.next, struct ctlr_info,
+                                       scan_list);
+                       list_del(&h->scan_list);
+                       h->busy_scanning = 1;
+                       mutex_unlock(&hpsa_scan_mutex);
+                       host_no = h->scsi_host ?  h->scsi_host->host_no : -1;
+                       hpsa_update_scsi_devices(h, host_no);
+                       complete_all(&h->scan_wait);
+                       mutex_lock(&hpsa_scan_mutex);
+                       h->busy_scanning = 0;
+                       mutex_unlock(&hpsa_scan_mutex);
+               }
+       }
+       return 0;
+}
+
+static int check_for_unit_attention(struct ctlr_info *h,
+       struct CommandList *c)
+{
+       if (c->err_info->SenseInfo[2] != UNIT_ATTENTION)
+               return 0;
+
+       switch (c->err_info->SenseInfo[12]) {
+       case STATE_CHANGED:
+               dev_warn(&h->pdev->dev, "hpsa%d: a state change "
+                       "detected, command retried\n", h->ctlr);
+               break;
+       case LUN_FAILED:
+               dev_warn(&h->pdev->dev, "hpsa%d: LUN failure "
+                       "detected, action required\n", h->ctlr);
+               break;
+       case REPORT_LUNS_CHANGED:
+               dev_warn(&h->pdev->dev, "hpsa%d: report LUN data "
+                       "changed\n", h->ctlr);
+       /*
+        * Here, we could call add_to_scan_list and wake up the scan thread,
+        * except that it's quite likely that we will get more than one
+        * REPORT_LUNS_CHANGED condition in quick succession, which means
+        * that those which occur after the first one will likely happen
+        * *during* the hpsa_scan_thread's rescan.  And the rescan code is not
+        * robust enough to restart in the middle, undoing what it has already
+        * done, and it's not clear that it's even possible to do this, since
+        * part of what it does is notify the SCSI mid layer, which starts
+        * doing it's own i/o to read partition tables and so on, and the
+        * driver doesn't have visibility to know what might need undoing.
+        * In any event, if possible, it is horribly complicated to get right
+        * so we just don't do it for now.
+        *
+        * Note: this REPORT_LUNS_CHANGED condition only occurs on the MSA2012.
+        */
+               break;
+       case POWER_OR_RESET:
+               dev_warn(&h->pdev->dev, "hpsa%d: a power on "
+                       "or device reset detected\n", h->ctlr);
+               break;
+       case UNIT_ATTENTION_CLEARED:
+               dev_warn(&h->pdev->dev, "hpsa%d: unit attention "
+                   "cleared by another initiator\n", h->ctlr);
+               break;
+       default:
+               dev_warn(&h->pdev->dev, "hpsa%d: unknown "
+                       "unit attention detected\n", h->ctlr);
+               break;
+       }
+       return 1;
+}
+
+static ssize_t host_store_rescan(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct ctlr_info *h;
+       struct Scsi_Host *shost = class_to_shost(dev);
+       unsigned long *priv = shost_priv(shost);
+       h = (struct ctlr_info *) *priv;
+       if (add_to_scan_list(h)) {
+               wake_up_process(hpsa_scan_thread);
+               wait_for_completion_interruptible(&h->scan_wait);
+       }
+       return count;
+}
+
+/* Enqueuing and dequeuing functions for cmdlists. */
+static inline void addQ(struct hlist_head *list, struct CommandList *c)
+{
+       hlist_add_head(&c->list, list);
+}
+
+static void enqueue_cmd_and_start_io(struct ctlr_info *h,
+       struct CommandList *c)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&h->lock, flags);
+       addQ(&h->reqQ, c);
+       h->Qdepth++;
+       start_io(h);
+       spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static inline void removeQ(struct CommandList *c)
+{
+       if (WARN_ON(hlist_unhashed(&c->list)))
+               return;
+       hlist_del_init(&c->list);
+}
+
+static inline int is_hba_lunid(unsigned char scsi3addr[])
+{
+       return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+}
+
+static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
+{
+       return (scsi3addr[3] & 0xC0) == 0x40;
+}
+
+static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
+       "UNKNOWN"
+};
+#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
+
+static ssize_t raid_level_show(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       ssize_t l = 0;
+       int rlevel;
+       struct ctlr_info *h;
+       struct scsi_device *sdev;
+       struct hpsa_scsi_dev_t *hdev;
+       unsigned long flags;
+
+       sdev = to_scsi_device(dev);
+       h = sdev_to_hba(sdev);
+       spin_lock_irqsave(&h->lock, flags);
+       hdev = sdev->hostdata;
+       if (!hdev) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               return -ENODEV;
+       }
+
+       /* Is this even a logical drive? */
+       if (!is_logical_dev_addr_mode(hdev->scsi3addr)) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               l = snprintf(buf, PAGE_SIZE, "N/A\n");
+               return l;
+       }
+
+       rlevel = hdev->raid_level;
+       spin_unlock_irqrestore(&h->lock, flags);
+       if (rlevel < 0 || rlevel > RAID_UNKNOWN)
+               rlevel = RAID_UNKNOWN;
+       l = snprintf(buf, PAGE_SIZE, "RAID %s\n", raid_label[rlevel]);
+       return l;
+}
+
+static ssize_t lunid_show(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       struct ctlr_info *h;
+       struct scsi_device *sdev;
+       struct hpsa_scsi_dev_t *hdev;
+       unsigned long flags;
+       unsigned char lunid[8];
+
+       sdev = to_scsi_device(dev);
+       h = sdev_to_hba(sdev);
+       spin_lock_irqsave(&h->lock, flags);
+       hdev = sdev->hostdata;
+       if (!hdev) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               return -ENODEV;
+       }
+       memcpy(lunid, hdev->scsi3addr, sizeof(lunid));
+       spin_unlock_irqrestore(&h->lock, flags);
+       return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+               lunid[0], lunid[1], lunid[2], lunid[3],
+               lunid[4], lunid[5], lunid[6], lunid[7]);
+}
+
+static ssize_t unique_id_show(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       struct ctlr_info *h;
+       struct scsi_device *sdev;
+       struct hpsa_scsi_dev_t *hdev;
+       unsigned long flags;
+       unsigned char sn[16];
+
+       sdev = to_scsi_device(dev);
+       h = sdev_to_hba(sdev);
+       spin_lock_irqsave(&h->lock, flags);
+       hdev = sdev->hostdata;
+       if (!hdev) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               return -ENODEV;
+       }
+       memcpy(sn, hdev->device_id, sizeof(sn));
+       spin_unlock_irqrestore(&h->lock, flags);
+       return snprintf(buf, 16 * 2 + 2,
+                       "%02X%02X%02X%02X%02X%02X%02X%02X"
+                       "%02X%02X%02X%02X%02X%02X%02X%02X\n",
+                       sn[0], sn[1], sn[2], sn[3],
+                       sn[4], sn[5], sn[6], sn[7],
+                       sn[8], sn[9], sn[10], sn[11],
+                       sn[12], sn[13], sn[14], sn[15]);
+}
+
+static int hpsa_find_target_lun(struct ctlr_info *h,
+       unsigned char scsi3addr[], int bus, int *target, int *lun)
+{
+       /* finds an unused bus, target, lun for a new physical device
+        * assumes h->devlock is held
+        */
+       int i, found = 0;
+       DECLARE_BITMAP(lun_taken, HPSA_MAX_SCSI_DEVS_PER_HBA);
+
+       memset(&lun_taken[0], 0, HPSA_MAX_SCSI_DEVS_PER_HBA >> 3);
+
+       for (i = 0; i < h->ndevices; i++) {
+               if (h->dev[i]->bus == bus && h->dev[i]->target != -1)
+                       set_bit(h->dev[i]->target, lun_taken);
+       }
+
+       for (i = 0; i < HPSA_MAX_SCSI_DEVS_PER_HBA; i++) {
+               if (!test_bit(i, lun_taken)) {
+                       /* *bus = 1; */
+                       *target = i;
+                       *lun = 0;
+                       found = 1;
+                       break;
+               }
+       }
+       return !found;
+}
+
+/* Add an entry into h->dev[] array. */
+static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
+               struct hpsa_scsi_dev_t *device,
+               struct hpsa_scsi_dev_t *added[], int *nadded)
+{
+       /* assumes h->devlock is held */
+       int n = h->ndevices;
+       int i;
+       unsigned char addr1[8], addr2[8];
+       struct hpsa_scsi_dev_t *sd;
+
+       if (n >= HPSA_MAX_SCSI_DEVS_PER_HBA) {
+               dev_err(&h->pdev->dev, "too many devices, some will be "
+                       "inaccessible.\n");
+               return -1;
+       }
+
+       /* physical devices do not have lun or target assigned until now. */
+       if (device->lun != -1)
+               /* Logical device, lun is already assigned. */
+               goto lun_assigned;
+
+       /* If this device a non-zero lun of a multi-lun device
+        * byte 4 of the 8-byte LUN addr will contain the logical
+        * unit no, zero otherise.
+        */
+       if (device->scsi3addr[4] == 0) {
+               /* This is not a non-zero lun of a multi-lun device */
+               if (hpsa_find_target_lun(h, device->scsi3addr,
+                       device->bus, &device->target, &device->lun) != 0)
+                       return -1;
+               goto lun_assigned;
+       }
+
+       /* This is a non-zero lun of a multi-lun device.
+        * Search through our list and find the device which
+        * has the same 8 byte LUN address, excepting byte 4.
+        * Assign the same bus and target for this new LUN.
+        * Use the logical unit number from the firmware.
+        */
+       memcpy(addr1, device->scsi3addr, 8);
+       addr1[4] = 0;
+       for (i = 0; i < n; i++) {
+               sd = h->dev[i];
+               memcpy(addr2, sd->scsi3addr, 8);
+               addr2[4] = 0;
+               /* differ only in byte 4? */
+               if (memcmp(addr1, addr2, 8) == 0) {
+                       device->bus = sd->bus;
+                       device->target = sd->target;
+                       device->lun = device->scsi3addr[4];
+                       break;
+               }
+       }
+       if (device->lun == -1) {
+               dev_warn(&h->pdev->dev, "physical device with no LUN=0,"
+                       " suspect firmware bug or unsupported hardware "
+                       "configuration.\n");
+                       return -1;
+       }
+
+lun_assigned:
+
+       h->dev[n] = device;
+       h->ndevices++;
+       added[*nadded] = device;
+       (*nadded)++;
+
+       /* initially, (before registering with scsi layer) we don't
+        * know our hostno and we don't want to print anything first
+        * time anyway (the scsi layer's inquiries will show that info)
+        */
+       /* if (hostno != -1) */
+               dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n",
+                       scsi_device_type(device->devtype), hostno,
+                       device->bus, device->target, device->lun);
+       return 0;
+}
+
+/* Remove an entry from h->dev[] array. */
+static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
+       struct hpsa_scsi_dev_t *removed[], int *nremoved)
+{
+       /* assumes h->devlock is held */
+       int i;
+       struct hpsa_scsi_dev_t *sd;
+
+       if (entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA)
+               BUG();
+
+       sd = h->dev[entry];
+       removed[*nremoved] = h->dev[entry];
+       (*nremoved)++;
+
+       for (i = entry; i < h->ndevices-1; i++)
+               h->dev[i] = h->dev[i+1];
+       h->ndevices--;
+       dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n",
+               scsi_device_type(sd->devtype), hostno, sd->bus, sd->target,
+               sd->lun);
+}
+
+#define SCSI3ADDR_EQ(a, b) ( \
+       (a)[7] == (b)[7] && \
+       (a)[6] == (b)[6] && \
+       (a)[5] == (b)[5] && \
+       (a)[4] == (b)[4] && \
+       (a)[3] == (b)[3] && \
+       (a)[2] == (b)[2] && \
+       (a)[1] == (b)[1] && \
+       (a)[0] == (b)[0])
+
+static void fixup_botched_add(struct ctlr_info *h,
+       struct hpsa_scsi_dev_t *added)
+{
+       /* called when scsi_add_device fails in order to re-adjust
+        * h->dev[] to match the mid layer's view.
+        */
+       unsigned long flags;
+       int i, j;
+
+       spin_lock_irqsave(&h->lock, flags);
+       for (i = 0; i < h->ndevices; i++) {
+               if (h->dev[i] == added) {
+                       for (j = i; j < h->ndevices-1; j++)
+                               h->dev[j] = h->dev[j+1];
+                       h->ndevices--;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&h->lock, flags);
+       kfree(added);
+}
+
+static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
+       struct hpsa_scsi_dev_t *dev2)
+{
+       if ((is_logical_dev_addr_mode(dev1->scsi3addr) ||
+               (dev1->lun != -1 && dev2->lun != -1)) &&
+               dev1->devtype != 0x0C)
+               return (memcmp(dev1, dev2, sizeof(*dev1)) == 0);
+
+       /* we compare everything except lun and target as these
+        * are not yet assigned.  Compare parts likely
+        * to differ first
+        */
+       if (memcmp(dev1->scsi3addr, dev2->scsi3addr,
+               sizeof(dev1->scsi3addr)) != 0)
+               return 0;
+       if (memcmp(dev1->device_id, dev2->device_id,
+               sizeof(dev1->device_id)) != 0)
+               return 0;
+       if (memcmp(dev1->model, dev2->model, sizeof(dev1->model)) != 0)
+               return 0;
+       if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0)
+               return 0;
+       if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0)
+               return 0;
+       if (dev1->devtype != dev2->devtype)
+               return 0;
+       if (dev1->raid_level != dev2->raid_level)
+               return 0;
+       if (dev1->bus != dev2->bus)
+               return 0;
+       return 1;
+}
+
+/* Find needle in haystack.  If exact match found, return DEVICE_SAME,
+ * and return needle location in *index.  If scsi3addr matches, but not
+ * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle
+ * location in *index.  If needle not found, return DEVICE_NOT_FOUND.
+ */
+static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
+       struct hpsa_scsi_dev_t *haystack[], int haystack_size,
+       int *index)
+{
+       int i;
+#define DEVICE_NOT_FOUND 0
+#define DEVICE_CHANGED 1
+#define DEVICE_SAME 2
+       for (i = 0; i < haystack_size; i++) {
+               if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) {
+                       *index = i;
+                       if (device_is_the_same(needle, haystack[i]))
+                               return DEVICE_SAME;
+                       else
+                               return DEVICE_CHANGED;
+               }
+       }
+       *index = -1;
+       return DEVICE_NOT_FOUND;
+}
+
+static int adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
+       struct hpsa_scsi_dev_t *sd[], int nsds)
+{
+       /* sd contains scsi3 addresses and devtypes, and inquiry
+        * data.  This function takes what's in sd to be the current
+        * reality and updates h->dev[] to reflect that reality.
+        */
+       int i, entry, device_change, changes = 0;
+       struct hpsa_scsi_dev_t *csd;
+       unsigned long flags;
+       struct hpsa_scsi_dev_t **added, **removed;
+       int nadded, nremoved;
+       struct Scsi_Host *sh = NULL;
+
+       added = kzalloc(sizeof(*added) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+               GFP_KERNEL);
+       removed = kzalloc(sizeof(*removed) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+               GFP_KERNEL);
+
+       if (!added || !removed) {
+               dev_warn(&h->pdev->dev, "out of memory in "
+                       "adjust_hpsa_scsi_table\n");
+               goto free_and_out;
+       }
+
+       spin_lock_irqsave(&h->devlock, flags);
+
+       /* find any devices in h->dev[] that are not in
+        * sd[] and remove them from h->dev[], and for any
+        * devices which have changed, remove the old device
+        * info and add the new device info.
+        */
+       i = 0;
+       nremoved = 0;
+       nadded = 0;
+       while (i < h->ndevices) {
+               csd = h->dev[i];
+               device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry);
+               if (device_change == DEVICE_NOT_FOUND) {
+                       changes++;
+                       hpsa_scsi_remove_entry(h, hostno, i,
+                               removed, &nremoved);
+                       continue; /* remove ^^^, hence i not incremented */
+               } else if (device_change == DEVICE_CHANGED) {
+                       changes++;
+                       hpsa_scsi_remove_entry(h, hostno, i,
+                               removed, &nremoved);
+                       (void) hpsa_scsi_add_entry(h, hostno, sd[entry],
+                               added, &nadded);
+                       /* add can't fail, we just removed one. */
+                       sd[entry] = NULL; /* prevent it from being freed */
+               }
+               i++;
+       }
+
+       /* Now, make sure every device listed in sd[] is also
+        * listed in h->dev[], adding them if they aren't found
+        */
+
+       for (i = 0; i < nsds; i++) {
+               if (!sd[i]) /* if already added above. */
+                       continue;
+               device_change = hpsa_scsi_find_entry(sd[i], h->dev,
+                                       h->ndevices, &entry);
+               if (device_change == DEVICE_NOT_FOUND) {
+                       changes++;
+                       if (hpsa_scsi_add_entry(h, hostno, sd[i],
+                               added, &nadded) != 0)
+                               break;
+                       sd[i] = NULL; /* prevent from being freed later. */
+               } else if (device_change == DEVICE_CHANGED) {
+                       /* should never happen... */
+                       changes++;
+                       dev_warn(&h->pdev->dev,
+                               "device unexpectedly changed.\n");
+                       /* but if it does happen, we just ignore that device */
+               }
+       }
+       spin_unlock_irqrestore(&h->devlock, flags);
+
+       /* Don't notify scsi mid layer of any changes the first time through
+        * (or if there are no changes) scsi_scan_host will do it later the
+        * first time through.
+        */
+       if (hostno == -1 || !changes)
+               goto free_and_out;
+
+       sh = h->scsi_host;
+       /* Notify scsi mid layer of any removed devices */
+       for (i = 0; i < nremoved; i++) {
+               struct scsi_device *sdev =
+                       scsi_device_lookup(sh, removed[i]->bus,
+                               removed[i]->target, removed[i]->lun);
+               if (sdev != NULL) {
+                       scsi_remove_device(sdev);
+                       scsi_device_put(sdev);
+               } else {
+                       /* We don't expect to get here.
+                        * future cmds to this device will get selection
+                        * timeout as if the device was gone.
+                        */
+                       dev_warn(&h->pdev->dev, "didn't find c%db%dt%dl%d "
+                               " for removal.", hostno, removed[i]->bus,
+                               removed[i]->target, removed[i]->lun);
+               }
+               kfree(removed[i]);
+               removed[i] = NULL;
+       }
+
+       /* Notify scsi mid layer of any added devices */
+       for (i = 0; i < nadded; i++) {
+               if (scsi_add_device(sh, added[i]->bus,
+                       added[i]->target, added[i]->lun) == 0)
+                       continue;
+               dev_warn(&h->pdev->dev, "scsi_add_device c%db%dt%dl%d failed, "
+                       "device not added.\n", hostno, added[i]->bus,
+                       added[i]->target, added[i]->lun);
+               /* now we have to remove it from h->dev,
+                * since it didn't get added to scsi mid layer
+                */
+               fixup_botched_add(h, added[i]);
+       }
+
+free_and_out:
+       kfree(added);
+       kfree(removed);
+       return 0;
+}
+
+/*
+ * Lookup bus/target/lun and retrun corresponding struct hpsa_scsi_dev_t *
+ * Assume's h->devlock is held.
+ */
+static struct hpsa_scsi_dev_t *lookup_hpsa_scsi_dev(struct ctlr_info *h,
+       int bus, int target, int lun)
+{
+       int i;
+       struct hpsa_scsi_dev_t *sd;
+
+       for (i = 0; i < h->ndevices; i++) {
+               sd = h->dev[i];
+               if (sd->bus == bus && sd->target == target && sd->lun == lun)
+                       return sd;
+       }
+       return NULL;
+}
+
+/* link sdev->hostdata to our per-device structure. */
+static int hpsa_slave_alloc(struct scsi_device *sdev)
+{
+       struct hpsa_scsi_dev_t *sd;
+       unsigned long flags;
+       struct ctlr_info *h;
+
+       h = sdev_to_hba(sdev);
+       spin_lock_irqsave(&h->devlock, flags);
+       sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
+               sdev_id(sdev), sdev->lun);
+       if (sd != NULL)
+               sdev->hostdata = sd;
+       spin_unlock_irqrestore(&h->devlock, flags);
+       return 0;
+}
+
+static void hpsa_slave_destroy(struct scsi_device *sdev)
+{
+       return; /* nothing to do. */
+}
+
+static void hpsa_scsi_setup(struct ctlr_info *h)
+{
+       h->ndevices = 0;
+       h->scsi_host = NULL;
+       spin_lock_init(&h->devlock);
+       return;
+}
+
+static void complete_scsi_command(struct CommandList *cp,
+       int timeout, __u32 tag)
+{
+       struct scsi_cmnd *cmd;
+       struct ctlr_info *h;
+       struct ErrorInfo *ei;
+
+       unsigned char sense_key;
+       unsigned char asc;      /* additional sense code */
+       unsigned char ascq;     /* additional sense code qualifier */
+
+       ei = cp->err_info;
+       cmd = (struct scsi_cmnd *) cp->scsi_cmd;
+       h = cp->h;
+
+       scsi_dma_unmap(cmd); /* undo the DMA mappings */
+
+       cmd->result = (DID_OK << 16);           /* host byte */
+       cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
+       cmd->result |= (ei->ScsiStatus << 1);
+
+       /* copy the sense data whether we need to or not. */
+       memcpy(cmd->sense_buffer, ei->SenseInfo,
+               ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
+                       SCSI_SENSE_BUFFERSIZE :
+                       ei->SenseLen);
+       scsi_set_resid(cmd, ei->ResidualCnt);
+
+       if (ei->CommandStatus == 0) {
+               cmd->scsi_done(cmd);
+               cmd_free(h, cp);
+               return;
+       }
+
+       /* an error has occurred */
+       switch (ei->CommandStatus) {
+
+       case CMD_TARGET_STATUS:
+               if (ei->ScsiStatus) {
+                       /* Get sense key */
+                       sense_key = 0xf & ei->SenseInfo[2];
+                       /* Get additional sense code */
+                       asc = ei->SenseInfo[12];
+                       /* Get addition sense code qualifier */
+                       ascq = ei->SenseInfo[13];
+               }
+
+               if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
+                       if (check_for_unit_attention(h, cp)) {
+                               cmd->result = DID_SOFT_ERROR << 16;
+                               break;
+                       }
+                       if (sense_key == ILLEGAL_REQUEST) {
+                               /*
+                                * SCSI REPORT_LUNS is commonly unsupported on
+                                * Smart Array.  Suppress noisy complaint.
+                                */
+                               if (cp->Request.CDB[0] == REPORT_LUNS)
+                                       break;
+
+                               /* If ASC/ASCQ indicate Logical Unit
+                                * Not Supported condition,
+                                */
+                               if ((asc == 0x25) && (ascq == 0x0)) {
+                                       dev_warn(&h->pdev->dev, "cp %p "
+                                               "has check condition\n", cp);
+                                       break;
+                               }
+                       }
+
+                       if (sense_key == NOT_READY) {
+                               /* If Sense is Not Ready, Logical Unit
+                                * Not ready, Manual Intervention
+                                * required
+                                */
+                               if ((asc == 0x04) && (ascq == 0x03)) {
+                                       cmd->result = DID_NO_CONNECT << 16;
+                                       dev_warn(&h->pdev->dev, "cp %p "
+                                               "has check condition: unit "
+                                               "not ready, manual "
+                                               "intervention required\n", cp);
+                                       break;
+                               }
+                       }
+
+
+                       /* Must be some other type of check condition */
+                       dev_warn(&h->pdev->dev, "cp %p has check condition: "
+                                       "unknown type: "
+                                       "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
+                                       "Returning result: 0x%x, "
+                                       "cmd=[%02x %02x %02x %02x %02x "
+                                       "%02x %02x %02x %02x %02x]\n",
+                                       cp, sense_key, asc, ascq,
+                                       cmd->result,
+                                       cmd->cmnd[0], cmd->cmnd[1],
+                                       cmd->cmnd[2], cmd->cmnd[3],
+                                       cmd->cmnd[4], cmd->cmnd[5],
+                                       cmd->cmnd[6], cmd->cmnd[7],
+                                       cmd->cmnd[8], cmd->cmnd[9]);
+                       break;
+               }
+
+
+               /* Problem was not a check condition
+                * Pass it up to the upper layers...
+                */
+               if (ei->ScsiStatus) {
+                       dev_warn(&h->pdev->dev, "cp %p has status 0x%x "
+                               "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
+                               "Returning result: 0x%x\n",
+                               cp, ei->ScsiStatus,
+                               sense_key, asc, ascq,
+                               cmd->result);
+               } else {  /* scsi status is zero??? How??? */
+                       dev_warn(&h->pdev->dev, "cp %p SCSI status was 0. "
+                               "Returning no connection.\n", cp),
+
+                       /* Ordinarily, this case should never happen,
+                        * but there is a bug in some released firmware
+                        * revisions that allows it to happen if, for
+                        * example, a 4100 backplane loses power and
+                        * the tape drive is in it.  We assume that
+                        * it's a fatal error of some kind because we
+                        * can't show that it wasn't. We will make it
+                        * look like selection timeout since that is
+                        * the most common reason for this to occur,
+                        * and it's severe enough.
+                        */
+
+                       cmd->result = DID_NO_CONNECT << 16;
+               }
+               break;
+
+       case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
+               break;
+       case CMD_DATA_OVERRUN:
+               dev_warn(&h->pdev->dev, "cp %p has"
+                       " completed with data overrun "
+                       "reported\n", cp);
+               break;
+       case CMD_INVALID: {
+               /* print_bytes(cp, sizeof(*cp), 1, 0);
+               print_cmd(cp); */
+               /* We get CMD_INVALID if you address a non-existent device
+                * instead of a selection timeout (no response).  You will
+                * see this if you yank out a drive, then try to access it.
+                * This is kind of a shame because it means that any other
+                * CMD_INVALID (e.g. driver bug) will get interpreted as a
+                * missing target. */
+               cmd->result = DID_NO_CONNECT << 16;
+       }
+               break;
+       case CMD_PROTOCOL_ERR:
+               dev_warn(&h->pdev->dev, "cp %p has "
+                       "protocol error \n", cp);
+               break;
+       case CMD_HARDWARE_ERR:
+               cmd->result = DID_ERROR << 16;
+               dev_warn(&h->pdev->dev, "cp %p had  hardware error\n", cp);
+               break;
+       case CMD_CONNECTION_LOST:
+               cmd->result = DID_ERROR << 16;
+               dev_warn(&h->pdev->dev, "cp %p had connection lost\n", cp);
+               break;
+       case CMD_ABORTED:
+               cmd->result = DID_ABORT << 16;
+               dev_warn(&h->pdev->dev, "cp %p was aborted with status 0x%x\n",
+                               cp, ei->ScsiStatus);
+               break;
+       case CMD_ABORT_FAILED:
+               cmd->result = DID_ERROR << 16;
+               dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp);
+               break;
+       case CMD_UNSOLICITED_ABORT:
+               cmd->result = DID_ABORT << 16;
+               dev_warn(&h->pdev->dev, "cp %p aborted do to an unsolicited "
+                       "abort\n", cp);
+               break;
+       case CMD_TIMEOUT:
+               cmd->result = DID_TIME_OUT << 16;
+               dev_warn(&h->pdev->dev, "cp %p timedout\n", cp);
+               break;
+       default:
+               cmd->result = DID_ERROR << 16;
+               dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n",
+                               cp, ei->CommandStatus);
+       }
+       cmd->scsi_done(cmd);
+       cmd_free(h, cp);
+}
+
+static int hpsa_scsi_detect(struct ctlr_info *h)
+{
+       struct Scsi_Host *sh;
+       int error;
+
+       sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
+       if (sh == NULL)
+               goto fail;
+
+       sh->io_port = 0;
+       sh->n_io_port = 0;
+       sh->this_id = -1;
+       sh->max_channel = 3;
+       sh->max_cmd_len = MAX_COMMAND_SIZE;
+       sh->max_lun = HPSA_MAX_LUN;
+       sh->max_id = HPSA_MAX_LUN;
+       h->scsi_host = sh;
+       sh->hostdata[0] = (unsigned long) h;
+       sh->irq = h->intr[SIMPLE_MODE_INT];
+       sh->unique_id = sh->irq;
+       error = scsi_add_host(sh, &h->pdev->dev);
+       if (error)
+               goto fail_host_put;
+       scsi_scan_host(sh);
+       return 0;
+
+ fail_host_put:
+       dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_add_host"
+               " failed for controller %d\n", h->ctlr);
+       scsi_host_put(sh);
+       return -1;
+ fail:
+       dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_host_alloc"
+               " failed for controller %d\n", h->ctlr);
+       return -1;
+}
+
+static void hpsa_pci_unmap(struct pci_dev *pdev,
+       struct CommandList *c, int sg_used, int data_direction)
+{
+       int i;
+       union u64bit addr64;
+
+       for (i = 0; i < sg_used; i++) {
+               addr64.val32.lower = c->SG[i].Addr.lower;
+               addr64.val32.upper = c->SG[i].Addr.upper;
+               pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len,
+                       data_direction);
+       }
+}
+
+static void hpsa_map_one(struct pci_dev *pdev,
+               struct CommandList *cp,
+               unsigned char *buf,
+               size_t buflen,
+               int data_direction)
+{
+       __u64 addr64;
+
+       if (buflen == 0 || data_direction == PCI_DMA_NONE) {
+               cp->Header.SGList = 0;
+               cp->Header.SGTotal = 0;
+               return;
+       }
+
+       addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
+       cp->SG[0].Addr.lower =
+         (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+       cp->SG[0].Addr.upper =
+         (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+       cp->SG[0].Len = buflen;
+       cp->Header.SGList = (__u8) 1;   /* no. SGs contig in this cmd */
+       cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
+}
+
+static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h,
+       struct CommandList *c)
+{
+       DECLARE_COMPLETION_ONSTACK(wait);
+
+       c->waiting = &wait;
+       enqueue_cmd_and_start_io(h, c);
+       wait_for_completion(&wait);
+}
+
+static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h,
+       struct CommandList *c, int data_direction)
+{
+       int retry_count = 0;
+
+       do {
+               memset(c->err_info, 0, sizeof(c->err_info));
+               hpsa_scsi_do_simple_cmd_core(h, c);
+               retry_count++;
+       } while (check_for_unit_attention(h, c) && retry_count <= 3);
+       hpsa_pci_unmap(h->pdev, c, 1, data_direction);
+}
+
+static void hpsa_scsi_interpret_error(struct CommandList *cp)
+{
+       struct ErrorInfo *ei;
+       struct device *d = &cp->h->pdev->dev;
+
+       ei = cp->err_info;
+       switch (ei->CommandStatus) {
+       case CMD_TARGET_STATUS:
+               dev_warn(d, "cmd %p has completed with errors\n", cp);
+               dev_warn(d, "cmd %p has SCSI Status = %x\n", cp,
+                               ei->ScsiStatus);
+               if (ei->ScsiStatus == 0)
+                       dev_warn(d, "SCSI status is abnormally zero.  "
+                       "(probably indicates selection timeout "
+                       "reported incorrectly due to a known "
+                       "firmware bug, circa July, 2001.)\n");
+               break;
+       case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
+                       dev_info(d, "UNDERRUN\n");
+               break;
+       case CMD_DATA_OVERRUN:
+               dev_warn(d, "cp %p has completed with data overrun\n", cp);
+               break;
+       case CMD_INVALID: {
+               /* controller unfortunately reports SCSI passthru's
+                * to non-existent targets as invalid commands.
+                */
+               dev_warn(d, "cp %p is reported invalid (probably means "
+                       "target device no longer present)\n", cp);
+               /* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0);
+               print_cmd(cp);  */
+               }
+               break;
+       case CMD_PROTOCOL_ERR:
+               dev_warn(d, "cp %p has protocol error \n", cp);
+               break;
+       case CMD_HARDWARE_ERR:
+               /* cmd->result = DID_ERROR << 16; */
+               dev_warn(d, "cp %p had hardware error\n", cp);
+               break;
+       case CMD_CONNECTION_LOST:
+               dev_warn(d, "cp %p had connection lost\n", cp);
+               break;
+       case CMD_ABORTED:
+               dev_warn(d, "cp %p was aborted\n", cp);
+               break;
+       case CMD_ABORT_FAILED:
+               dev_warn(d, "cp %p reports abort failed\n", cp);
+               break;
+       case CMD_UNSOLICITED_ABORT:
+               dev_warn(d, "cp %p aborted due to an unsolicited abort\n", cp);
+               break;
+       case CMD_TIMEOUT:
+               dev_warn(d, "cp %p timed out\n", cp);
+               break;
+       default:
+               dev_warn(d, "cp %p returned unknown status %x\n", cp,
+                               ei->CommandStatus);
+       }
+}
+
+static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
+                       unsigned char page, unsigned char *buf,
+                       unsigned char bufsize)
+{
+       int rc = IO_OK;
+       struct CommandList *c;
+       struct ErrorInfo *ei;
+
+       c = cmd_special_alloc(h);
+
+       if (c == NULL) {                        /* trouble... */
+               dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+               return -1;
+       }
+
+       fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD);
+       hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
+       ei = c->err_info;
+       if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+               hpsa_scsi_interpret_error(c);
+               rc = -1;
+       }
+       cmd_special_free(h, c);
+       return rc;
+}
+
+static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr)
+{
+       int rc = IO_OK;
+       struct CommandList *c;
+       struct ErrorInfo *ei;
+
+       c = cmd_special_alloc(h);
+
+       if (c == NULL) {                        /* trouble... */
+               dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+               return -1;
+       }
+
+       fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, scsi3addr, TYPE_MSG);
+       hpsa_scsi_do_simple_cmd_core(h, c);
+       /* no unmap needed here because no data xfer. */
+
+       ei = c->err_info;
+       if (ei->CommandStatus != 0) {
+               hpsa_scsi_interpret_error(c);
+               rc = -1;
+       }
+       cmd_special_free(h, c);
+       return rc;
+}
+
+static void hpsa_get_raid_level(struct ctlr_info *h,
+       unsigned char *scsi3addr, unsigned char *raid_level)
+{
+       int rc;
+       unsigned char *buf;
+
+       *raid_level = RAID_UNKNOWN;
+       buf = kzalloc(64, GFP_KERNEL);
+       if (!buf)
+               return;
+       rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0xC1, buf, 64);
+       if (rc == 0)
+               *raid_level = buf[8];
+       if (*raid_level > RAID_UNKNOWN)
+               *raid_level = RAID_UNKNOWN;
+       kfree(buf);
+       return;
+}
+
+/* Get the device id from inquiry page 0x83 */
+static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
+       unsigned char *device_id, int buflen)
+{
+       int rc;
+       unsigned char *buf;
+
+       if (buflen > 16)
+               buflen = 16;
+       buf = kzalloc(64, GFP_KERNEL);
+       if (!buf)
+               return -1;
+       rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
+       if (rc == 0)
+               memcpy(device_id, &buf[8], buflen);
+       kfree(buf);
+       return rc != 0;
+}
+
+static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
+               struct ReportLUNdata *buf, int bufsize,
+               int extended_response)
+{
+       int rc = IO_OK;
+       struct CommandList *c;
+       unsigned char scsi3addr[8];
+       struct ErrorInfo *ei;
+
+       c = cmd_special_alloc(h);
+       if (c == NULL) {                        /* trouble... */
+               dev_err(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+               return -1;
+       }
+
+       memset(&scsi3addr[0], 0, 8); /* address the controller */
+
+       fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h,
+               buf, bufsize, 0, scsi3addr, TYPE_CMD);
+       if (extended_response)
+               c->Request.CDB[1] = extended_response;
+       hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
+       ei = c->err_info;
+       if (ei->CommandStatus != 0 &&
+           ei->CommandStatus != CMD_DATA_UNDERRUN) {
+               hpsa_scsi_interpret_error(c);
+               rc = -1;
+       }
+       cmd_special_free(h, c);
+       return rc;
+}
+
+static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
+               struct ReportLUNdata *buf,
+               int bufsize, int extended_response)
+{
+       return hpsa_scsi_do_report_luns(h, 0, buf, bufsize, extended_response);
+}
+
+static inline int hpsa_scsi_do_report_log_luns(struct ctlr_info *h,
+               struct ReportLUNdata *buf, int bufsize)
+{
+       return hpsa_scsi_do_report_luns(h, 1, buf, bufsize, 0);
+}
+
+static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device,
+       int bus, int target, int lun)
+{
+       device->bus = bus;
+       device->target = target;
+       device->lun = lun;
+}
+
+static int hpsa_update_device_info(struct ctlr_info *h,
+       unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device)
+{
+#define OBDR_TAPE_INQ_SIZE 49
+       unsigned char *inq_buff = NULL;
+
+       inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
+       if (!inq_buff)
+               goto bail_out;
+
+       memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
+       /* Do an inquiry to the device to see what it is. */
+       if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
+               (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
+               /* Inquiry failed (msg printed already) */
+               dev_err(&h->pdev->dev,
+                       "hpsa_update_device_info: inquiry failed\n");
+               goto bail_out;
+       }
+
+       /* As a side effect, record the firmware version number
+        * if we happen to be talking to the RAID controller.
+        */
+       if (is_hba_lunid(scsi3addr))
+               memcpy(h->firm_ver, &inq_buff[32], 4);
+
+       this_device->devtype = (inq_buff[0] & 0x1f);
+       memcpy(this_device->scsi3addr, scsi3addr, 8);
+       memcpy(this_device->vendor, &inq_buff[8],
+               sizeof(this_device->vendor));
+       memcpy(this_device->model, &inq_buff[16],
+               sizeof(this_device->model));
+       memcpy(this_device->revision, &inq_buff[32],
+               sizeof(this_device->revision));
+       memset(this_device->device_id, 0,
+               sizeof(this_device->device_id));
+       hpsa_get_device_id(h, scsi3addr, this_device->device_id,
+               sizeof(this_device->device_id));
+
+       if (this_device->devtype == TYPE_DISK &&
+               is_logical_dev_addr_mode(scsi3addr))
+               hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level);
+       else
+               this_device->raid_level = RAID_UNKNOWN;
+
+       kfree(inq_buff);
+       return 0;
+
+bail_out:
+       kfree(inq_buff);
+       return 1;
+}
+
+static unsigned char *msa2xxx_model[] = {
+       "MSA2012",
+       "MSA2024",
+       "MSA2312",
+       "MSA2324",
+       NULL,
+};
+
+static int is_msa2xxx(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
+{
+       int i;
+
+       for (i = 0; msa2xxx_model[i]; i++)
+               if (strncmp(device->model, msa2xxx_model[i],
+                       strlen(msa2xxx_model[i])) == 0)
+                       return 1;
+       return 0;
+}
+
+/* Helper function to assign bus, target, lun mapping of devices.
+ * Puts non-msa2xxx logical volumes on bus 0, msa2xxx logical
+ * volumes on bus 1, physical devices on bus 2. and the hba on bus 3.
+ * Logical drive target and lun are assigned at this time, but
+ * physical device lun and target assignment are deferred (assigned
+ * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
+ */
+static void figure_bus_target_lun(struct ctlr_info *h,
+       __u8 *lunaddrbytes, int *bus, int *target, int *lun,
+       struct hpsa_scsi_dev_t *device)
+{
+
+       __u32 lunid;
+
+       if (is_logical_dev_addr_mode(lunaddrbytes)) {
+               /* logical device */
+               memcpy(&lunid, lunaddrbytes, sizeof(lunid));
+               lunid = le32_to_cpu(lunid);
+
+               if (is_msa2xxx(h, device)) {
+                       *bus = 1;
+                       *target = (lunid >> 16) & 0x3fff;
+                       *lun = lunid & 0x00ff;
+               } else {
+                       *bus = 0;
+                       *lun = 0;
+                       *target = lunid & 0x3fff;
+               }
+       } else {
+               /* physical device */
+               if (is_hba_lunid(lunaddrbytes))
+                       *bus = 3;
+               else
+                       *bus = 2;
+               *target = -1;
+               *lun = -1; /* we will fill these in later. */
+       }
+}
+
+/*
+ * If there is no lun 0 on a target, linux won't find any devices.
+ * For the MSA2xxx boxes, we have to manually detect the enclosure
+ * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report
+ * it for some reason.  *tmpdevice is the target we're adding,
+ * this_device is a pointer into the current element of currentsd[]
+ * that we're building up in update_scsi_devices(), below.
+ * lunzerobits is a bitmap that tracks which targets already have a
+ * lun 0 assigned.
+ * Returns 1 if an enclosure was added, 0 if not.
+ */
+static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
+       struct hpsa_scsi_dev_t *tmpdevice,
+       struct hpsa_scsi_dev_t *this_device, __u8 *lunaddrbytes,
+       int bus, int target, int lun, unsigned long lunzerobits[],
+       int *nmsa2xxx_enclosures)
+{
+       unsigned char scsi3addr[8];
+
+       if (test_bit(target, lunzerobits))
+               return 0; /* There is already a lun 0 on this target. */
+
+       if (!is_logical_dev_addr_mode(lunaddrbytes))
+               return 0; /* It's the logical targets that may lack lun 0. */
+
+       if (!is_msa2xxx(h, tmpdevice))
+               return 0; /* It's only the MSA2xxx that have this problem. */
+
+       if (lun == 0) /* if lun is 0, then obviously we have a lun 0. */
+               return 0;
+
+       if (is_hba_lunid(scsi3addr))
+               return 0; /* Don't add the RAID controller here. */
+
+#define MAX_MSA2XXX_ENCLOSURES 32
+       if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) {
+               dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX "
+                       "enclosures exceeded.  Check your hardware "
+                       "configuration.");
+               return 0;
+       }
+
+       memset(scsi3addr, 0, 8);
+       scsi3addr[3] = target;
+       if (hpsa_update_device_info(h, scsi3addr, this_device))
+               return 0;
+       (*nmsa2xxx_enclosures)++;
+       hpsa_set_bus_target_lun(this_device, bus, target, 0);
+       set_bit(target, lunzerobits);
+       return 1;
+}
+
+/*
+ * Do CISS_REPORT_PHYS and CISS_REPORT_LOG.  Data is returned in physdev,
+ * logdev.  The number of luns in physdev and logdev are returned in
+ * *nphysicals and *nlogicals, respectively.
+ * Returns 0 on success, -1 otherwise.
+ */
+static int hpsa_gather_lun_info(struct ctlr_info *h,
+       int reportlunsize,
+       struct ReportLUNdata *physdev, __u32 *nphysicals,
+       struct ReportLUNdata *logdev, __u32 *nlogicals)
+{
+       if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize, 0)) {
+               dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
+               return -1;
+       }
+       memcpy(nphysicals, &physdev->LUNListLength[0], sizeof(*nphysicals));
+       *nphysicals = be32_to_cpu(*nphysicals) / 8;
+#ifdef DEBUG
+       dev_info(&h->pdev->dev, "number of physical luns is %d\n", *nphysicals);
+#endif
+       if (*nphysicals > HPSA_MAX_PHYS_LUN) {
+               dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded."
+                       "  %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
+                       *nphysicals - HPSA_MAX_PHYS_LUN);
+               *nphysicals = HPSA_MAX_PHYS_LUN;
+       }
+       if (hpsa_scsi_do_report_log_luns(h, logdev, reportlunsize)) {
+               dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
+               return -1;
+       }
+       memcpy(nlogicals, &logdev->LUNListLength[0], sizeof(*nlogicals));
+       *nlogicals = be32_to_cpu(*nlogicals) / 8;
+#ifdef DEBUG
+       dev_info(&h->pdev->dev, "number of logical luns is %d\n", *nlogicals);
+#endif
+       /* Reject Logicals in excess of our max capability. */
+       if (*nlogicals > HPSA_MAX_LUN) {
+               dev_warn(&h->pdev->dev,
+                       "maximum logical LUNs (%d) exceeded.  "
+                       "%d LUNs ignored.\n", HPSA_MAX_LUN,
+                       *nlogicals - HPSA_MAX_LUN);
+                       *nlogicals = HPSA_MAX_LUN;
+       }
+       if (*nlogicals + *nphysicals > HPSA_MAX_PHYS_LUN) {
+               dev_warn(&h->pdev->dev,
+                       "maximum logical + physical LUNs (%d) exceeded. "
+                       "%d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
+                       *nphysicals + *nlogicals - HPSA_MAX_PHYS_LUN);
+               *nlogicals = HPSA_MAX_PHYS_LUN - *nphysicals;
+       }
+       return 0;
+}
+
+static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
+{
+       /* the idea here is we could get notified
+        * that some devices have changed, so we do a report
+        * physical luns and report logical luns cmd, and adjust
+        * our list of devices accordingly.
+        *
+        * The scsi3addr's of devices won't change so long as the
+        * adapter is not reset.  That means we can rescan and
+        * tell which devices we already know about, vs. new
+        * devices, vs.  disappearing devices.
+        */
+       struct ReportLUNdata *physdev_list = NULL;
+       struct ReportLUNdata *logdev_list = NULL;
+       unsigned char *inq_buff = NULL;
+       __u32 nphysicals = 0;
+       __u32 nlogicals = 0;
+       __u32 ndev_allocated = 0;
+       struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
+       int ncurrent = 0;
+       int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8;
+       int i, nmsa2xxx_enclosures, ndevs_to_allocate;
+       int bus, target, lun;
+       DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR);
+
+       currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+               GFP_KERNEL);
+       physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+       logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+       inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
+       tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
+
+       if (!currentsd || !physdev_list || !logdev_list ||
+               !inq_buff || !tmpdevice) {
+               dev_err(&h->pdev->dev, "out of memory\n");
+               goto out;
+       }
+       memset(lunzerobits, 0, sizeof(lunzerobits));
+
+       if (hpsa_gather_lun_info(h, reportlunsize, physdev_list, &nphysicals,
+                       logdev_list, &nlogicals))
+               goto out;
+
+       /* We might see up to 32 MSA2xxx enclosures, actually 8 of them
+        * but each of them 4 times through different paths.  The plus 1
+        * is for the RAID controller.
+        */
+       ndevs_to_allocate = nphysicals + nlogicals + MAX_MSA2XXX_ENCLOSURES + 1;
+
+       /* Allocate the per device structures */
+       for (i = 0; i < ndevs_to_allocate; i++) {
+               currentsd[i] = kzalloc(sizeof(*currentsd[i]), GFP_KERNEL);
+               if (!currentsd[i]) {
+                       dev_warn(&h->pdev->dev, "out of memory at %s:%d\n",
+                               __FILE__, __LINE__);
+                       goto out;
+               }
+               ndev_allocated++;
+       }
+
+       /* adjust our table of devices */
+       nmsa2xxx_enclosures = 0;
+       for (i = 0; i < nphysicals + nlogicals + 1; i++) {
+               __u8 *lunaddrbytes;
+
+               /* Figure out where the LUN ID info is coming from */
+               if (i < nphysicals)
+                       lunaddrbytes = &physdev_list->LUN[i][0];
+               else
+                       if (i < nphysicals + nlogicals)
+                               lunaddrbytes =
+                                       &logdev_list->LUN[i-nphysicals][0];
+                       else /* jam in the RAID controller at the end */
+                               lunaddrbytes = RAID_CTLR_LUNID;
+
+               /* skip masked physical devices. */
+               if (lunaddrbytes[3] & 0xC0 && i < nphysicals)
+                       continue;
+
+               /* Get device type, vendor, model, device id */
+               if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice))
+                       continue; /* skip it if we can't talk to it. */
+               figure_bus_target_lun(h, lunaddrbytes, &bus, &target, &lun,
+                       tmpdevice);
+               this_device = currentsd[ncurrent];
+
+               /*
+                * For the msa2xxx boxes, we have to insert a LUN 0 which
+                * doesn't show up in CCISS_REPORT_PHYSICAL data, but there
+                * is nonetheless an enclosure device there.  We have to
+                * present that otherwise linux won't find anything if
+                * there is no lun 0.
+                */
+               if (add_msa2xxx_enclosure_device(h, tmpdevice, this_device,
+                               lunaddrbytes, bus, target, lun, lunzerobits,
+                               &nmsa2xxx_enclosures)) {
+                       ncurrent++;
+                       this_device = currentsd[ncurrent];
+               }
+
+               *this_device = *tmpdevice;
+               hpsa_set_bus_target_lun(this_device, bus, target, lun);
+
+               switch (this_device->devtype) {
+               case TYPE_ROM: {
+                       /* We don't *really* support actual CD-ROM devices,
+                        * just "One Button Disaster Recovery" tape drive
+                        * which temporarily pretends to be a CD-ROM drive.
+                        * So we check that the device is really an OBDR tape
+                        * device by checking for "$DR-10" in bytes 43-48 of
+                        * the inquiry data.
+                        */
+                               char obdr_sig[7];
+#define OBDR_TAPE_SIG "$DR-10"
+                               strncpy(obdr_sig, &inq_buff[43], 6);
+                               obdr_sig[6] = '\0';
+                               if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+                                       /* Not OBDR device, ignore it. */
+                                       break;
+                       }
+                       ncurrent++;
+                       break;
+               case TYPE_DISK:
+                       if (i < nphysicals)
+                               break;
+                       ncurrent++;
+                       break;
+               case TYPE_TAPE:
+               case TYPE_MEDIUM_CHANGER:
+                       ncurrent++;
+                       break;
+               case TYPE_RAID:
+                       /* Only present the Smartarray HBA as a RAID controller.
+                        * If it's a RAID controller other than the HBA itself
+                        * (an external RAID controller, MSA500 or similar)
+                        * don't present it.
+                        */
+                       if (!is_hba_lunid(lunaddrbytes))
+                               break;
+                       ncurrent++;
+                       break;
+               default:
+                       break;
+               }
+               if (ncurrent >= HPSA_MAX_SCSI_DEVS_PER_HBA)
+                       break;
+       }
+       adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
+out:
+       kfree(tmpdevice);
+       for (i = 0; i < ndev_allocated; i++)
+               kfree(currentsd[i]);
+       kfree(currentsd);
+       kfree(inq_buff);
+       kfree(physdev_list);
+       kfree(logdev_list);
+       return;
+}
+
+/* hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
+ * dma mapping  and fills in the scatter gather entries of the
+ * hpsa command, cp.
+ */
+static int hpsa_scatter_gather(struct pci_dev *pdev,
+               struct CommandList *cp,
+               struct scsi_cmnd *cmd)
+{
+       unsigned int len;
+       struct scatterlist *sg;
+       __u64 addr64;
+       int use_sg, i;
+
+       BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
+
+       use_sg = scsi_dma_map(cmd);
+       if (use_sg < 0)
+               return use_sg;
+
+       if (!use_sg)
+               goto sglist_finished;
+
+       scsi_for_each_sg(cmd, sg, use_sg, i) {
+               addr64 = (__u64) sg_dma_address(sg);
+               len  = sg_dma_len(sg);
+               cp->SG[i].Addr.lower =
+                       (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+               cp->SG[i].Addr.upper =
+                       (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+               cp->SG[i].Len = len;
+               cp->SG[i].Ext = 0;  /* we are not chaining */
+       }
+
+sglist_finished:
+
+       cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
+       cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
+       return 0;
+}
+
+
+static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
+       void (*done)(struct scsi_cmnd *))
+{
+       struct ctlr_info *h;
+       struct hpsa_scsi_dev_t *dev;
+       unsigned char scsi3addr[8];
+       struct CommandList *c;
+       unsigned long flags;
+
+       /* Get the ptr to our adapter structure out of cmd->host. */
+       h = sdev_to_hba(cmd->device);
+       dev = cmd->device->hostdata;
+       if (!dev) {
+               cmd->result = DID_NO_CONNECT << 16;
+               done(cmd);
+               return 0;
+       }
+       memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
+
+       /* Need a lock as this is being allocated from the pool */
+       spin_lock_irqsave(&h->lock, flags);
+       c = cmd_alloc(h);
+       spin_unlock_irqrestore(&h->lock, flags);
+       if (c == NULL) {                        /* trouble... */
+               dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       /* Fill in the command list header */
+
+       cmd->scsi_done = done;    /* save this for use by completion code */
+
+       /* save c in case we have to abort it  */
+       cmd->host_scribble = (unsigned char *) c;
+
+       c->cmd_type = CMD_SCSI;
+       c->scsi_cmd = cmd;
+       c->Header.ReplyQueue = 0;  /* unused in simple mode */
+       memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
+       c->Header.Tag.lower = c->busaddr;  /* Use k. address of cmd as tag */
+
+       /* Fill in the request block... */
+
+       c->Request.Timeout = 0;
+       memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
+       BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
+       c->Request.CDBLen = cmd->cmd_len;
+       memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
+       c->Request.Type.Type = TYPE_CMD;
+       c->Request.Type.Attribute = ATTR_SIMPLE;
+       switch (cmd->sc_data_direction) {
+       case DMA_TO_DEVICE:
+               c->Request.Type.Direction = XFER_WRITE;
+               break;
+       case DMA_FROM_DEVICE:
+               c->Request.Type.Direction = XFER_READ;
+               break;
+       case DMA_NONE:
+               c->Request.Type.Direction = XFER_NONE;
+               break;
+       case DMA_BIDIRECTIONAL:
+               /* This can happen if a buggy application does a scsi passthru
+                * and sets both inlen and outlen to non-zero. ( see
+                * ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
+                */
+
+               c->Request.Type.Direction = XFER_RSVD;
+               /* This is technically wrong, and hpsa controllers should
+                * reject it with CMD_INVALID, which is the most correct
+                * response, but non-fibre backends appear to let it
+                * slide by, and give the same results as if this field
+                * were set correctly.  Either way is acceptable for
+                * our purposes here.
+                */
+
+               break;
+
+       default:
+               dev_err(&h->pdev->dev, "unknown data direction: %d\n",
+                       cmd->sc_data_direction);
+               BUG();
+               break;
+       }
+
+       if (hpsa_scatter_gather(h->pdev, c, cmd) < 0) { /* Fill SG list */
+               cmd_free(h, c);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+       enqueue_cmd_and_start_io(h, c);
+       /* the cmd'll come back via intr handler in complete_scsi_command()  */
+       return 0;
+}
+
+static void hpsa_unregister_scsi(struct ctlr_info *h)
+{
+       /* we are being forcibly unloaded, and may not refuse. */
+       scsi_remove_host(h->scsi_host);
+       scsi_host_put(h->scsi_host);
+       h->scsi_host = NULL;
+}
+
+static int hpsa_register_scsi(struct ctlr_info *h)
+{
+       int rc;
+
+       hpsa_update_scsi_devices(h, -1);
+       rc = hpsa_scsi_detect(h);
+       if (rc != 0)
+               dev_err(&h->pdev->dev, "hpsa_register_scsi: failed"
+                       " hpsa_scsi_detect(), rc is %d\n", rc);
+       return rc;
+}
+
+static int wait_for_device_to_become_ready(struct ctlr_info *h,
+       unsigned char lunaddr[])
+{
+       int rc = 0;
+       int count = 0;
+       int waittime = 1; /* seconds */
+       struct CommandList *c;
+
+       c = cmd_special_alloc(h);
+       if (!c) {
+               dev_warn(&h->pdev->dev, "out of memory in "
+                       "wait_for_device_to_become_ready.\n");
+               return IO_ERROR;
+       }
+
+       /* Send test unit ready until device ready, or give up. */
+       while (count < HPSA_TUR_RETRY_LIMIT) {
+
+               /* Wait for a bit.  do this first, because if we send
+                * the TUR right away, the reset will just abort it.
+                */
+               msleep(1000 * waittime);
+               count++;
+
+               /* Increase wait time with each try, up to a point. */
+               if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS)
+                       waittime = waittime * 2;
+
+               /* Send the Test Unit Ready */
+               fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, lunaddr, TYPE_CMD);
+               hpsa_scsi_do_simple_cmd_core(h, c);
+               /* no unmap needed here because no data xfer. */
+
+               if (c->err_info->CommandStatus == CMD_SUCCESS)
+                       break;
+
+               if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+                       c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION &&
+                       (c->err_info->SenseInfo[2] == NO_SENSE ||
+                       c->err_info->SenseInfo[2] == UNIT_ATTENTION))
+                       break;
+
+               dev_warn(&h->pdev->dev, "waiting %d secs "
+                       "for device to become ready.\n", waittime);
+               rc = 1; /* device not ready. */
+       }
+
+       if (rc)
+               dev_warn(&h->pdev->dev, "giving up on device.\n");
+       else
+               dev_warn(&h->pdev->dev, "device is ready.\n");
+
+       cmd_special_free(h, c);
+       return rc;
+}
+
+/* Need at least one of these error handlers to keep ../scsi/hosts.c from
+ * complaining.  Doing a host- or bus-reset can't do anything good here.
+ */
+static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
+{
+       int rc;
+       struct ctlr_info *h;
+       struct hpsa_scsi_dev_t *dev;
+
+       /* find the controller to which the command to be aborted was sent */
+       h = sdev_to_hba(scsicmd->device);
+       if (h == NULL) /* paranoia */
+               return FAILED;
+       dev_warn(&h->pdev->dev, "resetting drive\n");
+
+       dev = scsicmd->device->hostdata;
+       if (!dev) {
+               dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: "
+                       "device lookup failed.\n");
+               return FAILED;
+       }
+       /* send a reset to the SCSI LUN which the command was sent to */
+       rc = hpsa_send_reset(h, dev->scsi3addr);
+       if (rc == 0 && wait_for_device_to_become_ready(h, dev->scsi3addr) == 0)
+               return SUCCESS;
+
+       dev_warn(&h->pdev->dev, "resetting device failed.\n");
+       return FAILED;
+}
+
+/*
+ * For operations that cannot sleep, a command block is allocated at init,
+ * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
+ * which ones are free or in use.  Lock must be held when calling this.
+ * cmd_free() is the complement.
+ */
+static struct CommandList *cmd_alloc(struct ctlr_info *h)
+{
+       struct CommandList *c;
+       int i;
+       union u64bit temp64;
+       dma_addr_t cmd_dma_handle, err_dma_handle;
+
+       do {
+               i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
+               if (i == h->nr_cmds)
+                       return NULL;
+       } while (test_and_set_bit
+                (i & (BITS_PER_LONG - 1),
+                 h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
+       c = h->cmd_pool + i;
+       memset(c, 0, sizeof(*c));
+       cmd_dma_handle = h->cmd_pool_dhandle
+           + i * sizeof(*c);
+       c->err_info = h->errinfo_pool + i;
+       memset(c->err_info, 0, sizeof(*c->err_info));
+       err_dma_handle = h->errinfo_pool_dhandle
+           + i * sizeof(*c->err_info);
+       h->nr_allocs++;
+
+       c->cmdindex = i;
+
+       INIT_HLIST_NODE(&c->list);
+       c->busaddr = (__u32) cmd_dma_handle;
+       temp64.val = (__u64) err_dma_handle;
+       c->ErrDesc.Addr.lower = temp64.val32.lower;
+       c->ErrDesc.Addr.upper = temp64.val32.upper;
+       c->ErrDesc.Len = sizeof(*c->err_info);
+
+       c->h = h;
+       return c;
+}
+
+/* For operations that can wait for kmalloc to possibly sleep,
+ * this routine can be called. Lock need not be held to call
+ * cmd_special_alloc. cmd_special_free() is the complement.
+ */
+static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
+{
+       struct CommandList *c;
+       union u64bit temp64;
+       dma_addr_t cmd_dma_handle, err_dma_handle;
+
+       c = pci_alloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
+       if (c == NULL)
+               return NULL;
+       memset(c, 0, sizeof(*c));
+
+       c->cmdindex = -1;
+
+       c->err_info = pci_alloc_consistent(h->pdev, sizeof(*c->err_info),
+                   &err_dma_handle);
+
+       if (c->err_info == NULL) {
+               pci_free_consistent(h->pdev,
+                       sizeof(*c), c, cmd_dma_handle);
+               return NULL;
+       }
+       memset(c->err_info, 0, sizeof(*c->err_info));
+
+       INIT_HLIST_NODE(&c->list);
+       c->busaddr = (__u32) cmd_dma_handle;
+       temp64.val = (__u64) err_dma_handle;
+       c->ErrDesc.Addr.lower = temp64.val32.lower;
+       c->ErrDesc.Addr.upper = temp64.val32.upper;
+       c->ErrDesc.Len = sizeof(*c->err_info);
+
+       c->h = h;
+       return c;
+}
+
+static void cmd_free(struct ctlr_info *h, struct CommandList *c)
+{
+       int i;
+
+       i = c - h->cmd_pool;
+       clear_bit(i & (BITS_PER_LONG - 1),
+                 h->cmd_pool_bits + (i / BITS_PER_LONG));
+       h->nr_frees++;
+}
+
+static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
+{
+       union u64bit temp64;
+
+       temp64.val32.lower = c->ErrDesc.Addr.lower;
+       temp64.val32.upper = c->ErrDesc.Addr.upper;
+       pci_free_consistent(h->pdev, sizeof(*c->err_info),
+                           c->err_info, (dma_addr_t) temp64.val);
+       pci_free_consistent(h->pdev, sizeof(*c),
+                           c, (dma_addr_t) c->busaddr);
+}
+
+#ifdef CONFIG_COMPAT
+
+static int do_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+       int ret;
+
+       lock_kernel();
+       ret = hpsa_ioctl(dev, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
+       int cmd, void *arg);
+
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+       switch (cmd) {
+       case CCISS_GETPCIINFO:
+       case CCISS_GETINTINFO:
+       case CCISS_SETINTINFO:
+       case CCISS_GETNODENAME:
+       case CCISS_SETNODENAME:
+       case CCISS_GETHEARTBEAT:
+       case CCISS_GETBUSTYPES:
+       case CCISS_GETFIRMVER:
+       case CCISS_GETDRIVVER:
+       case CCISS_REVALIDVOLS:
+       case CCISS_DEREGDISK:
+       case CCISS_REGNEWDISK:
+       case CCISS_REGNEWD:
+       case CCISS_RESCANDISK:
+       case CCISS_GETLUNINFO:
+               return do_ioctl(dev, cmd, arg);
+
+       case CCISS_PASSTHRU32:
+               return hpsa_ioctl32_passthru(dev, cmd, arg);
+       case CCISS_BIG_PASSTHRU32:
+               return hpsa_ioctl32_big_passthru(dev, cmd, arg);
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
+{
+       IOCTL32_Command_struct __user *arg32 =
+           (IOCTL32_Command_struct __user *) arg;
+       IOCTL_Command_struct arg64;
+       IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
+       int err;
+       u32 cp;
+
+       err = 0;
+       err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+                          sizeof(arg64.LUN_info));
+       err |= copy_from_user(&arg64.Request, &arg32->Request,
+                          sizeof(arg64.Request));
+       err |= copy_from_user(&arg64.error_info, &arg32->error_info,
+                          sizeof(arg64.error_info));
+       err |= get_user(arg64.buf_size, &arg32->buf_size);
+       err |= get_user(cp, &arg32->buf);
+       arg64.buf = compat_ptr(cp);
+       err |= copy_to_user(p, &arg64, sizeof(arg64));
+
+       if (err)
+               return -EFAULT;
+
+       err = do_ioctl(dev, CCISS_PASSTHRU, (void *)p);
+       if (err)
+               return err;
+       err |= copy_in_user(&arg32->error_info, &p->error_info,
+                        sizeof(arg32->error_info));
+       if (err)
+               return -EFAULT;
+       return err;
+}
+
+static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
+       int cmd, void *arg)
+{
+       BIG_IOCTL32_Command_struct __user *arg32 =
+           (BIG_IOCTL32_Command_struct __user *) arg;
+       BIG_IOCTL_Command_struct arg64;
+       BIG_IOCTL_Command_struct __user *p =
+           compat_alloc_user_space(sizeof(arg64));
+       int err;
+       u32 cp;
+
+       err = 0;
+       err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+                          sizeof(arg64.LUN_info));
+       err |= copy_from_user(&arg64.Request, &arg32->Request,
+                          sizeof(arg64.Request));
+       err |= copy_from_user(&arg64.error_info, &arg32->error_info,
+                          sizeof(arg64.error_info));
+       err |= get_user(arg64.buf_size, &arg32->buf_size);
+       err |= get_user(arg64.malloc_size, &arg32->malloc_size);
+       err |= get_user(cp, &arg32->buf);
+       arg64.buf = compat_ptr(cp);
+       err |= copy_to_user(p, &arg64, sizeof(arg64));
+
+       if (err)
+               return -EFAULT;
+
+       err = do_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
+       if (err)
+               return err;
+       err |= copy_in_user(&arg32->error_info, &p->error_info,
+                        sizeof(arg32->error_info));
+       if (err)
+               return -EFAULT;
+       return err;
+}
+#endif
+
+static int hpsa_getpciinfo_ioctl(struct ctlr_info *h, void __user *argp)
+{
+       struct hpsa_pci_info pciinfo;
+
+       if (!argp)
+               return -EINVAL;
+       pciinfo.domain = pci_domain_nr(h->pdev->bus);
+       pciinfo.bus = h->pdev->bus->number;
+       pciinfo.dev_fn = h->pdev->devfn;
+       pciinfo.board_id = h->board_id;
+       if (copy_to_user(argp, &pciinfo, sizeof(pciinfo)))
+               return -EFAULT;
+       return 0;
+}
+
+static int hpsa_getdrivver_ioctl(struct ctlr_info *h, void __user *argp)
+{
+       DriverVer_type DriverVer;
+       unsigned char vmaj, vmin, vsubmin;
+       int rc;
+
+       rc = sscanf(HPSA_DRIVER_VERSION, "%hhu.%hhu.%hhu",
+               &vmaj, &vmin, &vsubmin);
+       if (rc != 3) {
+               dev_info(&h->pdev->dev, "driver version string '%s' "
+                       "unrecognized.", HPSA_DRIVER_VERSION);
+               vmaj = 0;
+               vmin = 0;
+               vsubmin = 0;
+       }
+       DriverVer = (vmaj << 16) | (vmin << 8) | vsubmin;
+       if (!argp)
+               return -EINVAL;
+       if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+               return -EFAULT;
+       return 0;
+}
+
+static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+{
+       IOCTL_Command_struct iocommand;
+       struct CommandList *c;
+       char *buff = NULL;
+       union u64bit temp64;
+
+       if (!argp)
+               return -EINVAL;
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+       if (copy_from_user(&iocommand, argp, sizeof(iocommand)))
+               return -EFAULT;
+       if ((iocommand.buf_size < 1) &&
+           (iocommand.Request.Type.Direction != XFER_NONE)) {
+               return -EINVAL;
+       }
+       if (iocommand.buf_size > 0) {
+               buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+               if (buff == NULL)
+                       return -EFAULT;
+       }
+       if (iocommand.Request.Type.Direction == XFER_WRITE) {
+               /* Copy the data into the buffer we created */
+               if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
+                       kfree(buff);
+                       return -EFAULT;
+               }
+       } else
+               memset(buff, 0, iocommand.buf_size);
+       c = cmd_special_alloc(h);
+       if (c == NULL) {
+               kfree(buff);
+               return -ENOMEM;
+       }
+       /* Fill in the command type */
+       c->cmd_type = CMD_IOCTL_PEND;
+       /* Fill in Command Header */
+       c->Header.ReplyQueue = 0; /* unused in simple mode */
+       if (iocommand.buf_size > 0) {   /* buffer to fill */
+               c->Header.SGList = 1;
+               c->Header.SGTotal = 1;
+       } else  { /* no buffers to fill */
+               c->Header.SGList = 0;
+               c->Header.SGTotal = 0;
+       }
+       memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
+       /* use the kernel address the cmd block for tag */
+       c->Header.Tag.lower = c->busaddr;
+
+       /* Fill in Request block */
+       memcpy(&c->Request, &iocommand.Request,
+               sizeof(c->Request));
+
+       /* Fill in the scatter gather information */
+       if (iocommand.buf_size > 0) {
+               temp64.val = pci_map_single(h->pdev, buff,
+                       iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+               c->SG[0].Addr.lower = temp64.val32.lower;
+               c->SG[0].Addr.upper = temp64.val32.upper;
+               c->SG[0].Len = iocommand.buf_size;
+               c->SG[0].Ext = 0; /* we are not chaining*/
+       }
+       hpsa_scsi_do_simple_cmd_core(h, c);
+       hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
+       check_ioctl_unit_attention(h, c);
+
+       /* Copy the error information out */
+       memcpy(&iocommand.error_info, c->err_info,
+               sizeof(iocommand.error_info));
+       if (copy_to_user(argp, &iocommand, sizeof(iocommand))) {
+               kfree(buff);
+               cmd_special_free(h, c);
+               return -EFAULT;
+       }
+
+       if (iocommand.Request.Type.Direction == XFER_READ) {
+               /* Copy the data out of the buffer we created */
+               if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+                       kfree(buff);
+                       cmd_special_free(h, c);
+                       return -EFAULT;
+               }
+       }
+       kfree(buff);
+       cmd_special_free(h, c);
+       return 0;
+}
+
+static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+{
+       BIG_IOCTL_Command_struct *ioc;
+       struct CommandList *c;
+       unsigned char **buff = NULL;
+       int *buff_size = NULL;
+       union u64bit temp64;
+       BYTE sg_used = 0;
+       int status = 0;
+       int i;
+       __u32 left;
+       __u32 sz;
+       BYTE __user *data_ptr;
+
+       if (!argp)
+               return -EINVAL;
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+       ioc = (BIG_IOCTL_Command_struct *)
+           kmalloc(sizeof(*ioc), GFP_KERNEL);
+       if (!ioc) {
+               status = -ENOMEM;
+               goto cleanup1;
+       }
+       if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+               status = -EFAULT;
+               goto cleanup1;
+       }
+       if ((ioc->buf_size < 1) &&
+           (ioc->Request.Type.Direction != XFER_NONE)) {
+               status = -EINVAL;
+               goto cleanup1;
+       }
+       /* Check kmalloc limits  using all SGs */
+       if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+               status = -EINVAL;
+               goto cleanup1;
+       }
+       if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+               status = -EINVAL;
+               goto cleanup1;
+       }
+       buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+       if (!buff) {
+               status = -ENOMEM;
+               goto cleanup1;
+       }
+       buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+       if (!buff_size) {
+               status = -ENOMEM;
+               goto cleanup1;
+       }
+       left = ioc->buf_size;
+       data_ptr = ioc->buf;
+       while (left) {
+               sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+               buff_size[sg_used] = sz;
+               buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+               if (buff[sg_used] == NULL) {
+                       status = -ENOMEM;
+                       goto cleanup1;
+               }
+               if (ioc->Request.Type.Direction == XFER_WRITE) {
+                       if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+                               status = -ENOMEM;
+                               goto cleanup1;
+                       }
+               } else
+                       memset(buff[sg_used], 0, sz);
+               left -= sz;
+               data_ptr += sz;
+               sg_used++;
+       }
+       c = cmd_special_alloc(h);
+       if (c == NULL) {
+               status = -ENOMEM;
+               goto cleanup1;
+       }
+       c->cmd_type = CMD_IOCTL_PEND;
+       c->Header.ReplyQueue = 0;
+
+       if (ioc->buf_size > 0) {
+               c->Header.SGList = sg_used;
+               c->Header.SGTotal = sg_used;
+       } else {
+               c->Header.SGList = 0;
+               c->Header.SGTotal = 0;
+       }
+       memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
+       c->Header.Tag.lower = c->busaddr;
+       memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
+       if (ioc->buf_size > 0) {
+               int i;
+               for (i = 0; i < sg_used; i++) {
+                       temp64.val = pci_map_single(h->pdev, buff[i],
+                                   buff_size[i], PCI_DMA_BIDIRECTIONAL);
+                       c->SG[i].Addr.lower = temp64.val32.lower;
+                       c->SG[i].Addr.upper = temp64.val32.upper;
+                       c->SG[i].Len = buff_size[i];
+                       /* we are not chaining */
+                       c->SG[i].Ext = 0;
+               }
+       }
+       hpsa_scsi_do_simple_cmd_core(h, c);
+       hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
+       check_ioctl_unit_attention(h, c);
+       /* Copy the error information out */
+       memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
+       if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+               cmd_special_free(h, c);
+               status = -EFAULT;
+               goto cleanup1;
+       }
+       if (ioc->Request.Type.Direction == XFER_READ) {
+               /* Copy the data out of the buffer we created */
+               BYTE __user *ptr = ioc->buf;
+               for (i = 0; i < sg_used; i++) {
+                       if (copy_to_user(ptr, buff[i], buff_size[i])) {
+                               cmd_special_free(h, c);
+                               status = -EFAULT;
+                               goto cleanup1;
+                       }
+                       ptr += buff_size[i];
+               }
+       }
+       cmd_special_free(h, c);
+       status = 0;
+cleanup1:
+       if (buff) {
+               for (i = 0; i < sg_used; i++)
+                       kfree(buff[i]);
+               kfree(buff);
+       }
+       kfree(buff_size);
+       kfree(ioc);
+       return status;
+}
+
+static void check_ioctl_unit_attention(struct ctlr_info *h,
+       struct CommandList *c)
+{
+       if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+                       c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
+               (void) check_for_unit_attention(h, c);
+}
+/*
+ * ioctl
+ */
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+       struct ctlr_info *h;
+       void __user *argp = (void __user *)arg;
+
+       h = sdev_to_hba(dev);
+
+       switch (cmd) {
+       case CCISS_DEREGDISK:
+       case CCISS_REGNEWDISK:
+       case CCISS_REGNEWD:
+               hpsa_update_scsi_devices(h, dev->host->host_no);
+               return 0;
+       case CCISS_GETPCIINFO:
+               return hpsa_getpciinfo_ioctl(h, argp);
+       case CCISS_GETDRIVVER:
+               return hpsa_getdrivver_ioctl(h, argp);
+       case CCISS_PASSTHRU:
+               return hpsa_passthru_ioctl(h, argp);
+       case CCISS_BIG_PASSTHRU:
+               return hpsa_big_passthru_ioctl(h, argp);
+       default:
+               return -ENOTTY;
+       }
+}
+
+static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
+       void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+       int cmd_type)
+{
+       int pci_dir = XFER_NONE;
+
+       c->cmd_type = CMD_IOCTL_PEND;
+       c->Header.ReplyQueue = 0;
+       if (buff != NULL && size > 0) {
+               c->Header.SGList = 1;
+               c->Header.SGTotal = 1;
+       } else {
+               c->Header.SGList = 0;
+               c->Header.SGTotal = 0;
+       }
+       c->Header.Tag.lower = c->busaddr;
+       memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
+
+       c->Request.Type.Type = cmd_type;
+       if (cmd_type == TYPE_CMD) {
+               switch (cmd) {
+               case HPSA_INQUIRY:
+                       /* are we trying to read a vital product page */
+                       if (page_code != 0) {
+                               c->Request.CDB[1] = 0x01;
+                               c->Request.CDB[2] = page_code;
+                       }
+                       c->Request.CDBLen = 6;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = HPSA_INQUIRY;
+                       c->Request.CDB[4] = size & 0xFF;
+                       break;
+               case HPSA_REPORT_LOG:
+               case HPSA_REPORT_PHYS:
+                       /* Talking to controller so It's a physical command
+                          mode = 00 target = 0.  Nothing to write.
+                        */
+                       c->Request.CDBLen = 12;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = cmd;
+                       c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */
+                       c->Request.CDB[7] = (size >> 16) & 0xFF;
+                       c->Request.CDB[8] = (size >> 8) & 0xFF;
+                       c->Request.CDB[9] = size & 0xFF;
+                       break;
+
+               case HPSA_READ_CAPACITY:
+                       c->Request.CDBLen = 10;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = cmd;
+                       break;
+               case HPSA_CACHE_FLUSH:
+                       c->Request.CDBLen = 12;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_WRITE;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = BMIC_WRITE;
+                       c->Request.CDB[6] = BMIC_CACHE_FLUSH;
+                       break;
+               case TEST_UNIT_READY:
+                       c->Request.CDBLen = 6;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_NONE;
+                       c->Request.Timeout = 0;
+                       break;
+               default:
+                       dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
+                       BUG();
+                       return;
+               }
+       } else if (cmd_type == TYPE_MSG) {
+               switch (cmd) {
+
+               case  HPSA_DEVICE_RESET_MSG:
+                       c->Request.CDBLen = 16;
+                       c->Request.Type.Type =  1; /* It is a MSG not a CMD */
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_NONE;
+                       c->Request.Timeout = 0; /* Don't time out */
+                       c->Request.CDB[0] =  0x01; /* RESET_MSG is 0x01 */
+                       c->Request.CDB[1] = 0x03;  /* Reset target above */
+                       /* If bytes 4-7 are zero, it means reset the */
+                       /* LunID device */
+                       c->Request.CDB[4] = 0x00;
+                       c->Request.CDB[5] = 0x00;
+                       c->Request.CDB[6] = 0x00;
+                       c->Request.CDB[7] = 0x00;
+               break;
+
+               default:
+                       dev_warn(&h->pdev->dev, "unknown message type %d\n",
+                               cmd);
+                       BUG();
+               }
+       } else {
+               dev_warn(&h->pdev->dev, "unknown command type %d\n", cmd_type);
+               BUG();
+       }
+
+       switch (c->Request.Type.Direction) {
+       case XFER_READ:
+               pci_dir = PCI_DMA_FROMDEVICE;
+               break;
+       case XFER_WRITE:
+               pci_dir = PCI_DMA_TODEVICE;
+               break;
+       case XFER_NONE:
+               pci_dir = PCI_DMA_NONE;
+               break;
+       default:
+               pci_dir = PCI_DMA_BIDIRECTIONAL;
+       }
+
+       hpsa_map_one(h->pdev, c, buff, size, pci_dir);
+
+       return;
+}
+
+/*
+ * Map (physical) PCI mem into (virtual) kernel space
+ */
+static void __iomem *remap_pci_mem(ulong base, ulong size)
+{
+       ulong page_base = ((ulong) base) & PAGE_MASK;
+       ulong page_offs = ((ulong) base) - page_base;
+       void __iomem *page_remapped = ioremap(page_base, page_offs + size);
+
+       return page_remapped ? (page_remapped + page_offs) : NULL;
+}
+
+/* Takes cmds off the submission queue and sends them to the hardware,
+ * then puts them on the queue of cmds waiting for completion.
+ */
+static void start_io(struct ctlr_info *h)
+{
+       struct CommandList *c;
+
+       while (!hlist_empty(&h->reqQ)) {
+               c = hlist_entry(h->reqQ.first, struct CommandList, list);
+               /* can't do anything if fifo is full */
+               if ((h->access.fifo_full(h))) {
+                       dev_warn(&h->pdev->dev, "fifo full\n");
+                       break;
+               }
+
+               /* Get the first entry from the Request Q */
+               removeQ(c);
+               h->Qdepth--;
+
+               /* Tell the controller execute command */
+               h->access.submit_command(h, c);
+
+               /* Put job onto the completed Q */
+               addQ(&h->cmpQ, c);
+       }
+}
+
+static inline unsigned long get_next_completion(struct ctlr_info *h)
+{
+       return h->access.command_completed(h);
+}
+
+static inline int interrupt_pending(struct ctlr_info *h)
+{
+       return h->access.intr_pending(h);
+}
+
+static inline long interrupt_not_for_us(struct ctlr_info *h)
+{
+       return ((h->access.intr_pending(h) == 0) ||
+                (h->interrupts_enabled == 0));
+}
+
+static inline int bad_tag(struct ctlr_info *h, __u32 tag_index,
+       __u32 raw_tag)
+{
+       if (unlikely(tag_index >= h->nr_cmds)) {
+               dev_warn(&h->pdev->dev, "bad tag 0x%08x ignored.\n", raw_tag);
+               return 1;
+       }
+       return 0;
+}
+
+static inline void finish_cmd(struct CommandList *c, __u32 raw_tag)
+{
+       removeQ(c);
+       if (likely(c->cmd_type == CMD_SCSI))
+               complete_scsi_command(c, 0, raw_tag);
+       else if (c->cmd_type == CMD_IOCTL_PEND)
+               complete(c->waiting);
+}
+
+static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
+{
+       struct ctlr_info *h = dev_id;
+       struct CommandList *c;
+       unsigned long flags;
+       __u32 raw_tag, tag, tag_index;
+       struct hlist_node *tmp;
+
+       if (interrupt_not_for_us(h))
+               return IRQ_NONE;
+       spin_lock_irqsave(&h->lock, flags);
+       while (interrupt_pending(h)) {
+               while ((raw_tag = get_next_completion(h)) != FIFO_EMPTY) {
+                       if (likely(HPSA_TAG_CONTAINS_INDEX(raw_tag))) {
+                               tag_index = HPSA_TAG_TO_INDEX(raw_tag);
+                               if (bad_tag(h, tag_index, raw_tag))
+                                       return IRQ_HANDLED;
+                               c = h->cmd_pool + tag_index;
+                               finish_cmd(c, raw_tag);
+                               continue;
+                       }
+                       tag = HPSA_TAG_DISCARD_ERROR_BITS(raw_tag);
+                       c = NULL;
+                       hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+                               if (c->busaddr == tag) {
+                                       finish_cmd(c, raw_tag);
+                                       break;
+                               }
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&h->lock, flags);
+       return IRQ_HANDLED;
+}
+
+/* Send a message CDB to the firmware. */
+static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
+                                               unsigned char type)
+{
+       struct Command {
+               struct CommandListHeader CommandHeader;
+               struct RequestBlock Request;
+               struct ErrDescriptor ErrorDescriptor;
+       };
+       struct Command *cmd;
+       static const size_t cmd_sz = sizeof(*cmd) +
+                                       sizeof(cmd->ErrorDescriptor);
+       dma_addr_t paddr64;
+       uint32_t paddr32, tag;
+       void __iomem *vaddr;
+       int i, err;
+
+       vaddr = pci_ioremap_bar(pdev, 0);
+       if (vaddr == NULL)
+               return -ENOMEM;
+
+       /* The Inbound Post Queue only accepts 32-bit physical addresses for the
+        * CCISS commands, so they must be allocated from the lower 4GiB of
+        * memory.
+        */
+       err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (err) {
+               iounmap(vaddr);
+               return -ENOMEM;
+       }
+
+       cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);
+       if (cmd == NULL) {
+               iounmap(vaddr);
+               return -ENOMEM;
+       }
+
+       /* This must fit, because of the 32-bit consistent DMA mask.  Also,
+        * although there's no guarantee, we assume that the address is at
+        * least 4-byte aligned (most likely, it's page-aligned).
+        */
+       paddr32 = paddr64;
+
+       cmd->CommandHeader.ReplyQueue = 0;
+       cmd->CommandHeader.SGList = 0;
+       cmd->CommandHeader.SGTotal = 0;
+       cmd->CommandHeader.Tag.lower = paddr32;
+       cmd->CommandHeader.Tag.upper = 0;
+       memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
+
+       cmd->Request.CDBLen = 16;
+       cmd->Request.Type.Type = TYPE_MSG;
+       cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
+       cmd->Request.Type.Direction = XFER_NONE;
+       cmd->Request.Timeout = 0; /* Don't time out */
+       cmd->Request.CDB[0] = opcode;
+       cmd->Request.CDB[1] = type;
+       memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */
+       cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(*cmd);
+       cmd->ErrorDescriptor.Addr.upper = 0;
+       cmd->ErrorDescriptor.Len = sizeof(struct ErrorInfo);
+
+       writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
+
+       for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
+               tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
+               if (HPSA_TAG_DISCARD_ERROR_BITS(tag) == paddr32)
+                       break;
+               msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
+       }
+
+       iounmap(vaddr);
+
+       /* we leak the DMA buffer here ... no choice since the controller could
+        *  still complete the command.
+        */
+       if (i == HPSA_MSG_SEND_RETRY_LIMIT) {
+               dev_err(&pdev->dev, "controller message %02x:%02x timed out\n",
+                       opcode, type);
+               return -ETIMEDOUT;
+       }
+
+       pci_free_consistent(pdev, cmd_sz, cmd, paddr64);
+
+       if (tag & HPSA_ERROR_BIT) {
+               dev_err(&pdev->dev, "controller message %02x:%02x failed\n",
+                       opcode, type);
+               return -EIO;
+       }
+
+       dev_info(&pdev->dev, "controller message %02x:%02x succeeded\n",
+               opcode, type);
+       return 0;
+}
+
+#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
+#define hpsa_noop(p) hpsa_message(p, 3, 0)
+
+static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
+{
+/* the #defines are stolen from drivers/pci/msi.h. */
+#define msi_control_reg(base)          (base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE          (1 << 15)
+
+       int pos;
+       u16 control = 0;
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       if (pos) {
+               pci_read_config_word(pdev, msi_control_reg(pos), &control);
+               if (control & PCI_MSI_FLAGS_ENABLE) {
+                       dev_info(&pdev->dev, "resetting MSI\n");
+                       pci_write_config_word(pdev, msi_control_reg(pos),
+                                       control & ~PCI_MSI_FLAGS_ENABLE);
+               }
+       }
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+       if (pos) {
+               pci_read_config_word(pdev, msi_control_reg(pos), &control);
+               if (control & PCI_MSIX_FLAGS_ENABLE) {
+                       dev_info(&pdev->dev, "resetting MSI-X\n");
+                       pci_write_config_word(pdev, msi_control_reg(pos),
+                                       control & ~PCI_MSIX_FLAGS_ENABLE);
+               }
+       }
+
+       return 0;
+}
+
+/* This does a hard reset of the controller using PCI power management
+ * states.
+ */
+static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev)
+{
+       u16 pmcsr, saved_config_space[32];
+       int i, pos;
+
+       dev_info(&pdev->dev, "using PCI PM to reset controller\n");
+
+       /* This is very nearly the same thing as
+        *
+        * pci_save_state(pci_dev);
+        * pci_set_power_state(pci_dev, PCI_D3hot);
+        * pci_set_power_state(pci_dev, PCI_D0);
+        * pci_restore_state(pci_dev);
+        *
+        * but we can't use these nice canned kernel routines on
+        * kexec, because they also check the MSI/MSI-X state in PCI
+        * configuration space and do the wrong thing when it is
+        * set/cleared.  Also, the pci_save/restore_state functions
+        * violate the ordering requirements for restoring the
+        * configuration space from the CCISS document (see the
+        * comment below).  So we roll our own ....
+        */
+
+       for (i = 0; i < 32; i++)
+               pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
+       if (pos == 0) {
+               dev_err(&pdev->dev,
+                       "hpsa_reset_controller: PCI PM not supported\n");
+               return -ENODEV;
+       }
+
+       /* Quoting from the Open CISS Specification: "The Power
+        * Management Control/Status Register (CSR) controls the power
+        * state of the device.  The normal operating state is D0,
+        * CSR=00h.  The software off state is D3, CSR=03h.  To reset
+        * the controller, place the interface device in D3 then to
+        * D0, this causes a secondary PCI reset which will reset the
+        * controller."
+        */
+
+       /* enter the D3hot power management state */
+       pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pmcsr |= PCI_D3hot;
+       pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+       msleep(500);
+
+       /* enter the D0 power management state */
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pmcsr |= PCI_D0;
+       pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+       msleep(500);
+
+       /* Restore the PCI configuration space.  The Open CISS
+        * Specification says, "Restore the PCI Configuration
+        * Registers, offsets 00h through 60h. It is important to
+        * restore the command register, 16-bits at offset 04h,
+        * last. Do not restore the configuration status register,
+        * 16-bits at offset 06h."  Note that the offset is 2*i.
+        */
+       for (i = 0; i < 32; i++) {
+               if (i == 2 || i == 3)
+                       continue;
+               pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+       }
+       wmb();
+       pci_write_config_word(pdev, 4, saved_config_space[2]);
+
+       return 0;
+}
+
+/*
+ *  We cannot read the structure directly, for portability we must use
+ *   the io functions.
+ *   This is for debug only.
+ */
+#ifdef HPSA_DEBUG
+static void print_cfg_table(struct device *dev, struct CfgTable *tb)
+{
+       int i;
+       char temp_name[17];
+
+       dev_info(dev, "Controller Configuration information\n");
+       dev_info(dev, "------------------------------------\n");
+       for (i = 0; i < 4; i++)
+               temp_name[i] = readb(&(tb->Signature[i]));
+       temp_name[4] = '\0';
+       dev_info(dev, "   Signature = %s\n", temp_name);
+       dev_info(dev, "   Spec Number = %d\n", readl(&(tb->SpecValence)));
+       dev_info(dev, "   Transport methods supported = 0x%x\n",
+              readl(&(tb->TransportSupport)));
+       dev_info(dev, "   Transport methods active = 0x%x\n",
+              readl(&(tb->TransportActive)));
+       dev_info(dev, "   Requested transport Method = 0x%x\n",
+              readl(&(tb->HostWrite.TransportRequest)));
+       dev_info(dev, "   Coalesce Interrupt Delay = 0x%x\n",
+              readl(&(tb->HostWrite.CoalIntDelay)));
+       dev_info(dev, "   Coalesce Interrupt Count = 0x%x\n",
+              readl(&(tb->HostWrite.CoalIntCount)));
+       dev_info(dev, "   Max outstanding commands = 0x%d\n",
+              readl(&(tb->CmdsOutMax)));
+       dev_info(dev, "   Bus Types = 0x%x\n", readl(&(tb->BusTypes)));
+       for (i = 0; i < 16; i++)
+               temp_name[i] = readb(&(tb->ServerName[i]));
+       temp_name[16] = '\0';
+       dev_info(dev, "   Server Name = %s\n", temp_name);
+       dev_info(dev, "   Heartbeat Counter = 0x%x\n\n\n",
+               readl(&(tb->HeartBeat)));
+}
+#endif                         /* HPSA_DEBUG */
+
+static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
+{
+       int i, offset, mem_type, bar_type;
+
+       if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */
+               return 0;
+       offset = 0;
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE;
+               if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
+                       offset += 4;
+               else {
+                       mem_type = pci_resource_flags(pdev, i) &
+                           PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+                       switch (mem_type) {
+                       case PCI_BASE_ADDRESS_MEM_TYPE_32:
+                       case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+                               offset += 4;    /* 32 bit */
+                               break;
+                       case PCI_BASE_ADDRESS_MEM_TYPE_64:
+                               offset += 8;
+                               break;
+                       default:        /* reserved in PCI 2.2 */
+                               dev_warn(&pdev->dev,
+                                      "base address is invalid\n");
+                               return -1;
+                               break;
+                       }
+               }
+               if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
+                       return i + 1;
+       }
+       return -1;
+}
+
+/* If MSI/MSI-X is supported by the kernel we will try to enable it on
+ * controllers that are capable. If not, we use IO-APIC mode.
+ */
+
+static void __devinit hpsa_interrupt_mode(struct ctlr_info *h,
+                                          struct pci_dev *pdev, __u32 board_id)
+{
+#ifdef CONFIG_PCI_MSI
+       int err;
+       struct msix_entry hpsa_msix_entries[4] = { {0, 0}, {0, 1},
+       {0, 2}, {0, 3}
+       };
+
+       /* Some boards advertise MSI but don't really support it */
+       if ((board_id == 0x40700E11) ||
+           (board_id == 0x40800E11) ||
+           (board_id == 0x40820E11) || (board_id == 0x40830E11))
+               goto default_int_mode;
+       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+               dev_info(&pdev->dev, "MSIX\n");
+               err = pci_enable_msix(pdev, hpsa_msix_entries, 4);
+               if (!err) {
+                       h->intr[0] = hpsa_msix_entries[0].vector;
+                       h->intr[1] = hpsa_msix_entries[1].vector;
+                       h->intr[2] = hpsa_msix_entries[2].vector;
+                       h->intr[3] = hpsa_msix_entries[3].vector;
+                       h->msix_vector = 1;
+                       return;
+               }
+               if (err > 0) {
+                       dev_warn(&pdev->dev, "only %d MSI-X vectors "
+                              "available\n", err);
+                       goto default_int_mode;
+               } else {
+                       dev_warn(&pdev->dev, "MSI-X init failed %d\n",
+                              err);
+                       goto default_int_mode;
+               }
+       }
+       if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+               dev_info(&pdev->dev, "MSI\n");
+               if (!pci_enable_msi(pdev))
+                       h->msi_vector = 1;
+               else
+                       dev_warn(&pdev->dev, "MSI init failed\n");
+       }
+default_int_mode:
+#endif                         /* CONFIG_PCI_MSI */
+       /* if we get here we're going to use the default interrupt mode */
+       h->intr[SIMPLE_MODE_INT] = pdev->irq;
+       return;
+}
+
+static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
+{
+       ushort subsystem_vendor_id, subsystem_device_id, command;
+       __u32 board_id, scratchpad = 0;
+       __u64 cfg_offset;
+       __u32 cfg_base_addr;
+       __u64 cfg_base_addr_index;
+       int i, prod_index, err;
+
+       subsystem_vendor_id = pdev->subsystem_vendor;
+       subsystem_device_id = pdev->subsystem_device;
+       board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
+                   subsystem_vendor_id);
+
+       for (i = 0; i < ARRAY_SIZE(products); i++)
+               if (board_id == products[i].board_id)
+                       break;
+
+       prod_index = i;
+
+       if (prod_index == ARRAY_SIZE(products)) {
+               prod_index--;
+               if (subsystem_vendor_id != PCI_VENDOR_ID_HP ||
+                               !hpsa_allow_any) {
+                       dev_warn(&pdev->dev, "unrecognized board ID:"
+                               " 0x%08lx, ignoring.\n",
+                               (unsigned long) board_id);
+                       return -ENODEV;
+               }
+       }
+       /* check to see if controller has been disabled
+        * BEFORE trying to enable it
+        */
+       (void)pci_read_config_word(pdev, PCI_COMMAND, &command);
+       if (!(command & 0x02)) {
+               dev_warn(&pdev->dev, "controller appears to be disabled\n");
+               return -ENODEV;
+       }
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               dev_warn(&pdev->dev, "unable to enable PCI device\n");
+               return err;
+       }
+
+       err = pci_request_regions(pdev, "hpsa");
+       if (err) {
+               dev_err(&pdev->dev, "cannot obtain PCI resources, aborting\n");
+               return err;
+       }
+
+       /* If the kernel supports MSI/MSI-X we will try to enable that,
+        * else we use the IO-APIC interrupt assigned to us by system ROM.
+        */
+       hpsa_interrupt_mode(h, pdev, board_id);
+
+       /* find the memory BAR */
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               if (pci_resource_flags(pdev, i) & IORESOURCE_MEM)
+                       break;
+       }
+       if (i == DEVICE_COUNT_RESOURCE) {
+               dev_warn(&pdev->dev, "no memory BAR found\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+
+       h->paddr = pci_resource_start(pdev, i); /* addressing mode bits
+                                                * already removed
+                                                */
+
+       h->vaddr = remap_pci_mem(h->paddr, 0x250);
+
+       /* Wait for the board to become ready.  */
+       for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) {
+               scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
+               if (scratchpad == HPSA_FIRMWARE_READY)
+                       break;
+               msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS);
+       }
+       if (scratchpad != HPSA_FIRMWARE_READY) {
+               dev_warn(&pdev->dev, "board not ready, timed out.\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+
+       /* get the address index number */
+       cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET);
+       cfg_base_addr &= (__u32) 0x0000ffff;
+       cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
+       if (cfg_base_addr_index == -1) {
+               dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+
+       cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET);
+       h->cfgtable = remap_pci_mem(pci_resource_start(pdev,
+                              cfg_base_addr_index) + cfg_offset,
+                               sizeof(h->cfgtable));
+       h->board_id = board_id;
+
+       /* Query controller for max supported commands: */
+       h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+
+       h->product_name = products[prod_index].product_name;
+       h->access = *(products[prod_index].access);
+       /* Allow room for some ioctls */
+       h->nr_cmds = h->max_commands - 4;
+
+       if ((readb(&h->cfgtable->Signature[0]) != 'C') ||
+           (readb(&h->cfgtable->Signature[1]) != 'I') ||
+           (readb(&h->cfgtable->Signature[2]) != 'S') ||
+           (readb(&h->cfgtable->Signature[3]) != 'S')) {
+               dev_warn(&pdev->dev, "not a valid CISS config table\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+#ifdef CONFIG_X86
+       {
+               /* Need to enable prefetch in the SCSI core for 6400 in x86 */
+               __u32 prefetch;
+               prefetch = readl(&(h->cfgtable->SCSI_Prefetch));
+               prefetch |= 0x100;
+               writel(prefetch, &(h->cfgtable->SCSI_Prefetch));
+       }
+#endif
+
+       /* Disabling DMA prefetch for the P600
+        * An ASIC bug may result in a prefetch beyond
+        * physical memory.
+        */
+       if (board_id == 0x3225103C) {
+               __u32 dma_prefetch;
+               dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG);
+               dma_prefetch |= 0x8000;
+               writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
+       }
+
+       h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+       /* Update the field, and then ring the doorbell */
+       writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+       writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+
+       /* under certain very rare conditions, this can take awhile.
+        * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
+        * as we enter this code.)
+        */
+       for (i = 0; i < MAX_CONFIG_WAIT; i++) {
+               if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+                       break;
+               /* delay and try again */
+               msleep(10);
+       }
+
+#ifdef HPSA_DEBUG
+       print_cfg_table(&pdev->dev, h->cfgtable);
+#endif                         /* HPSA_DEBUG */
+
+       if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+               dev_warn(&pdev->dev, "unable to get board into simple mode\n");
+               err = -ENODEV;
+               goto err_out_free_res;
+       }
+       return 0;
+
+err_out_free_res:
+       /*
+        * Deliberately omit pci_disable_device(): it does something nasty to
+        * Smart Array controllers that pci_enable_device does not undo
+        */
+       pci_release_regions(pdev);
+       return err;
+}
+
+static int __devinit hpsa_init_one(struct pci_dev *pdev,
+                                   const struct pci_device_id *ent)
+{
+       int i;
+       int dac;
+       struct ctlr_info *h;
+
+       if (number_of_controllers == 0)
+               printk(KERN_INFO DRIVER_NAME "\n");
+       if (reset_devices) {
+               /* Reset the controller with a PCI power-cycle */
+               if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev))
+                       return -ENODEV;
+
+               /* Some devices (notably the HP Smart Array 5i Controller)
+                  need a little pause here */
+               msleep(HPSA_POST_RESET_PAUSE_MSECS);
+
+               /* Now try to get the controller to respond to a no-op */
+               for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
+                       if (hpsa_noop(pdev) == 0)
+                               break;
+                       else
+                               dev_warn(&pdev->dev, "no-op failed%s\n",
+                                               (i < 11 ? "; re-trying" : ""));
+               }
+       }
+
+       BUILD_BUG_ON(sizeof(struct CommandList) % 8);
+       h = kzalloc(sizeof(*h), GFP_KERNEL);
+       if (!h)
+               return -1;
+
+       h->busy_initializing = 1;
+       INIT_HLIST_HEAD(&h->cmpQ);
+       INIT_HLIST_HEAD(&h->reqQ);
+       mutex_init(&h->busy_shutting_down);
+       init_completion(&h->scan_wait);
+       if (hpsa_pci_init(h, pdev) != 0)
+               goto clean1;
+
+       sprintf(h->devname, "hpsa%d", number_of_controllers);
+       h->ctlr = number_of_controllers;
+       number_of_controllers++;
+       h->pdev = pdev;
+
+       /* configure PCI DMA stuff */
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
+               dac = 1;
+       else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
+               dac = 0;
+       else {
+               dev_err(&pdev->dev, "no suitable DMA available\n");
+               goto clean1;
+       }
+
+       /* make sure the board interrupts are off */
+       h->access.set_intr_mask(h, HPSA_INTR_OFF);
+       if (request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr,
+                       IRQF_DISABLED | IRQF_SHARED, h->devname, h)) {
+               dev_err(&pdev->dev, "unable to get irq %d for %s\n",
+                      h->intr[SIMPLE_MODE_INT], h->devname);
+               goto clean2;
+       }
+
+       dev_info(&pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
+              h->devname, pdev->device, pci_name(pdev),
+              h->intr[SIMPLE_MODE_INT], dac ? "" : " not");
+
+       h->cmd_pool_bits =
+           kmalloc(((h->nr_cmds + BITS_PER_LONG -
+                     1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
+       h->cmd_pool = pci_alloc_consistent(h->pdev,
+                   h->nr_cmds * sizeof(*h->cmd_pool),
+                   &(h->cmd_pool_dhandle));
+       h->errinfo_pool = pci_alloc_consistent(h->pdev,
+                   h->nr_cmds * sizeof(*h->errinfo_pool),
+                   &(h->errinfo_pool_dhandle));
+       if ((h->cmd_pool_bits == NULL)
+           || (h->cmd_pool == NULL)
+           || (h->errinfo_pool == NULL)) {
+               dev_err(&pdev->dev, "out of memory");
+               goto clean4;
+       }
+       spin_lock_init(&h->lock);
+
+       pci_set_drvdata(pdev, h);
+       memset(h->cmd_pool_bits, 0,
+              ((h->nr_cmds + BITS_PER_LONG -
+                1) / BITS_PER_LONG) * sizeof(unsigned long));
+
+       hpsa_scsi_setup(h);
+
+       /* Turn the interrupts on so we can service requests */
+       h->access.set_intr_mask(h, HPSA_INTR_ON);
+
+       hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
+       h->busy_initializing = 0;
+       return 1;
+
+clean4:
+       kfree(h->cmd_pool_bits);
+       if (h->cmd_pool)
+               pci_free_consistent(h->pdev,
+                           h->nr_cmds * sizeof(struct CommandList),
+                           h->cmd_pool, h->cmd_pool_dhandle);
+       if (h->errinfo_pool)
+               pci_free_consistent(h->pdev,
+                           h->nr_cmds * sizeof(struct ErrorInfo),
+                           h->errinfo_pool,
+                           h->errinfo_pool_dhandle);
+       free_irq(h->intr[SIMPLE_MODE_INT], h);
+clean2:
+clean1:
+       h->busy_initializing = 0;
+       kfree(h);
+       return -1;
+}
+
+static void hpsa_flush_cache(struct ctlr_info *h)
+{
+       char *flush_buf;
+       struct CommandList *c;
+
+       flush_buf = kzalloc(4, GFP_KERNEL);
+       if (!flush_buf)
+               return;
+
+       c = cmd_special_alloc(h);
+       if (!c) {
+               dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+               goto out_of_memory;
+       }
+       fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
+               RAID_CTLR_LUNID, TYPE_CMD);
+       hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_TODEVICE);
+       if (c->err_info->CommandStatus != 0)
+               dev_warn(&h->pdev->dev,
+                       "error flushing cache on controller\n");
+       cmd_special_free(h, c);
+out_of_memory:
+       kfree(flush_buf);
+}
+
+static void hpsa_shutdown(struct pci_dev *pdev)
+{
+       struct ctlr_info *h;
+
+       h = pci_get_drvdata(pdev);
+       /* Turn board interrupts off  and send the flush cache command
+        * sendcmd will turn off interrupt, and send the flush...
+        * To write all data in the battery backed cache to disks
+        */
+       hpsa_flush_cache(h);
+       h->access.set_intr_mask(h, HPSA_INTR_OFF);
+       free_irq(h->intr[2], h);
+#ifdef CONFIG_PCI_MSI
+       if (h->msix_vector)
+               pci_disable_msix(h->pdev);
+       else if (h->msi_vector)
+               pci_disable_msi(h->pdev);
+#endif                         /* CONFIG_PCI_MSI */
+}
+
+static void __devexit hpsa_remove_one(struct pci_dev *pdev)
+{
+       struct ctlr_info *h;
+
+       if (pci_get_drvdata(pdev) == NULL) {
+               dev_err(&pdev->dev, "unable to remove device \n");
+               return;
+       }
+       h = pci_get_drvdata(pdev);
+       mutex_lock(&h->busy_shutting_down);
+       remove_from_scan_list(h);
+       hpsa_unregister_scsi(h);        /* unhook from SCSI subsystem */
+       hpsa_shutdown(pdev);
+       iounmap(h->vaddr);
+       pci_free_consistent(h->pdev,
+               h->nr_cmds * sizeof(struct CommandList),
+               h->cmd_pool, h->cmd_pool_dhandle);
+       pci_free_consistent(h->pdev,
+               h->nr_cmds * sizeof(struct ErrorInfo),
+               h->errinfo_pool, h->errinfo_pool_dhandle);
+       kfree(h->cmd_pool_bits);
+       /*
+        * Deliberately omit pci_disable_device(): it does something nasty to
+        * Smart Array controllers that pci_enable_device does not undo
+        */
+       pci_release_regions(pdev);
+       pci_set_drvdata(pdev, NULL);
+       mutex_unlock(&h->busy_shutting_down);
+       kfree(h);
+}
+
+static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev,
+       __attribute__((unused)) pm_message_t state)
+{
+       return -ENOSYS;
+}
+
+static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev)
+{
+       return -ENOSYS;
+}
+
+static struct pci_driver hpsa_pci_driver = {
+       .name = "hpsa",
+       .probe = hpsa_init_one,
+       .remove = __devexit_p(hpsa_remove_one),
+       .id_table = hpsa_pci_device_id, /* id_table */
+       .shutdown = hpsa_shutdown,
+       .suspend = hpsa_suspend,
+       .resume = hpsa_resume,
+};
+
+/*
+ *  This is it.  Register the PCI driver information for the cards we control
+ *  the OS will call our registered routines when it finds one of our cards.
+ */
+static int __init hpsa_init(void)
+{
+       int err;
+       /* Start the scan thread */
+       hpsa_scan_thread = kthread_run(hpsa_scan_func, NULL, "hpsa_scan");
+       if (IS_ERR(hpsa_scan_thread)) {
+               err = PTR_ERR(hpsa_scan_thread);
+               return -ENODEV;
+       }
+       err = pci_register_driver(&hpsa_pci_driver);
+       if (err)
+               kthread_stop(hpsa_scan_thread);
+       return err;
+}
+
+static void __exit hpsa_cleanup(void)
+{
+       pci_unregister_driver(&hpsa_pci_driver);
+       kthread_stop(hpsa_scan_thread);
+}
+
+module_init(hpsa_init);
+module_exit(hpsa_cleanup);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
new file mode 100644 (file)
index 0000000..6bd1949
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; version 2 of the License.
+ *
+ *    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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+#ifndef HPSA_H
+#define HPSA_H
+
+#include <scsi/scsicam.h>
+
+#define IO_OK          0
+#define IO_ERROR       1
+
+struct ctlr_info;
+
+struct access_method {
+       void (*submit_command)(struct ctlr_info *h,
+               struct CommandList *c);
+       void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
+       unsigned long (*fifo_full)(struct ctlr_info *h);
+       unsigned long (*intr_pending)(struct ctlr_info *h);
+       unsigned long (*command_completed)(struct ctlr_info *h);
+};
+
+struct hpsa_scsi_dev_t {
+       int devtype;
+       int bus, target, lun;           /* as presented to the OS */
+       unsigned char scsi3addr[8];     /* as presented to the HW */
+#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
+       unsigned char device_id[16];    /* from inquiry pg. 0x83 */
+       unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
+       unsigned char model[16];        /* bytes 16-31 of inquiry data */
+       unsigned char revision[4];      /* bytes 32-35 of inquiry data */
+       unsigned char raid_level;       /* from inquiry page 0xC1 */
+};
+
+struct ctlr_info {
+       int     ctlr;
+       char    devname[8];
+       char    *product_name;
+       char    firm_ver[4]; /* Firmware version */
+       struct pci_dev *pdev;
+       __u32   board_id;
+       void __iomem *vaddr;
+       unsigned long paddr;
+       int     nr_cmds; /* Number of commands allowed on this controller */
+       struct CfgTable __iomem *cfgtable;
+       int     interrupts_enabled;
+       int     major;
+       int     max_commands;
+       int     commands_outstanding;
+       int     max_outstanding; /* Debug */
+       int     usage_count;  /* number of opens all all minor devices */
+#      define DOORBELL_INT     0
+#      define PERF_MODE_INT    1
+#      define SIMPLE_MODE_INT  2
+#      define MEMQ_MODE_INT    3
+       unsigned int intr[4];
+       unsigned int msix_vector;
+       unsigned int msi_vector;
+       struct access_method access;
+
+       /* queue and queue Info */
+       struct hlist_head reqQ;
+       struct hlist_head cmpQ;
+       unsigned int Qdepth;
+       unsigned int maxQsinceinit;
+       unsigned int maxSG;
+       spinlock_t lock;
+
+       /* pointers to command and error info pool */
+       struct CommandList      *cmd_pool;
+       dma_addr_t              cmd_pool_dhandle;
+       struct ErrorInfo        *errinfo_pool;
+       dma_addr_t              errinfo_pool_dhandle;
+       unsigned long           *cmd_pool_bits;
+       int                     nr_allocs;
+       int                     nr_frees;
+       int                     busy_initializing;
+       int                     busy_scanning;
+       struct mutex            busy_shutting_down;
+       struct list_head        scan_list;
+       struct completion       scan_wait;
+
+       struct Scsi_Host *scsi_host;
+       spinlock_t devlock; /* to protect hba[ctlr]->dev[];  */
+       int ndevices; /* number of used elements in .dev[] array. */
+#define HPSA_MAX_SCSI_DEVS_PER_HBA 256
+       struct hpsa_scsi_dev_t *dev[HPSA_MAX_SCSI_DEVS_PER_HBA];
+};
+#define HPSA_ABORT_MSG 0
+#define HPSA_DEVICE_RESET_MSG 1
+#define HPSA_BUS_RESET_MSG 2
+#define HPSA_HOST_RESET_MSG 3
+#define HPSA_MSG_SEND_RETRY_LIMIT 10
+#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS 1000
+
+/* Maximum time in seconds driver will wait for command completions
+ * when polling before giving up.
+ */
+#define HPSA_MAX_POLL_TIME_SECS (20)
+
+/* During SCSI error recovery, HPSA_TUR_RETRY_LIMIT defines
+ * how many times to retry TEST UNIT READY on a device
+ * while waiting for it to become ready before giving up.
+ * HPSA_MAX_WAIT_INTERVAL_SECS is the max wait interval
+ * between sending TURs while waiting for a device
+ * to become ready.
+ */
+#define HPSA_TUR_RETRY_LIMIT (20)
+#define HPSA_MAX_WAIT_INTERVAL_SECS (30)
+
+/* HPSA_BOARD_READY_WAIT_SECS is how long to wait for a board
+ * to become ready, in seconds, before giving up on it.
+ * HPSA_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait
+ * between polling the board to see if it is ready, in
+ * milliseconds.  HPSA_BOARD_READY_POLL_INTERVAL and
+ * HPSA_BOARD_READY_ITERATIONS are derived from those.
+ */
+#define HPSA_BOARD_READY_WAIT_SECS (120)
+#define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
+#define HPSA_BOARD_READY_POLL_INTERVAL \
+       ((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
+#define HPSA_BOARD_READY_ITERATIONS \
+       ((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
+               HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
+#define HPSA_POST_RESET_PAUSE_MSECS (3000)
+#define HPSA_POST_RESET_NOOP_RETRIES (12)
+
+/*  Defining the diffent access_menthods */
+/*
+ * Memory mapped FIFO interface (SMART 53xx cards)
+ */
+#define SA5_DOORBELL   0x20
+#define SA5_REQUEST_PORT_OFFSET        0x40
+#define SA5_REPLY_INTR_MASK_OFFSET     0x34
+#define SA5_REPLY_PORT_OFFSET          0x44
+#define SA5_INTR_STATUS                0x30
+#define SA5_SCRATCHPAD_OFFSET  0xB0
+
+#define SA5_CTCFG_OFFSET       0xB4
+#define SA5_CTMEM_OFFSET       0xB8
+
+#define SA5_INTR_OFF           0x08
+#define SA5B_INTR_OFF          0x04
+#define SA5_INTR_PENDING       0x08
+#define SA5B_INTR_PENDING      0x04
+#define FIFO_EMPTY             0xffffffff
+#define HPSA_FIRMWARE_READY    0xffff0000 /* value in scratchpad register */
+
+#define HPSA_ERROR_BIT         0x02
+#define HPSA_TAG_CONTAINS_INDEX(tag) ((tag) & 0x04)
+#define HPSA_TAG_TO_INDEX(tag) ((tag) >> 3)
+#define HPSA_TAG_DISCARD_ERROR_BITS(tag) ((tag) & ~3)
+
+#define HPSA_INTR_ON   1
+#define HPSA_INTR_OFF  0
+/*
+       Send the command to the hardware
+*/
+static void SA5_submit_command(struct ctlr_info *h,
+       struct CommandList *c)
+{
+#ifdef HPSA_DEBUG
+        printk(KERN_WARNING "hpsa: Sending %x - down to controller\n",
+               c->busaddr);
+#endif /* HPSA_DEBUG */
+       writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+       h->commands_outstanding++;
+       if (h->commands_outstanding > h->max_outstanding)
+               h->max_outstanding = h->commands_outstanding;
+}
+
+/*
+ *  This card is the opposite of the other cards.
+ *   0 turns interrupts on...
+ *   0x08 turns them off...
+ */
+static void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
+{
+       if (val) { /* Turn interrupts on */
+               h->interrupts_enabled = 1;
+               writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+       } else { /* Turn them off */
+               h->interrupts_enabled = 0;
+               writel(SA5_INTR_OFF,
+                       h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+       }
+}
+/*
+ *  Returns true if fifo is full.
+ *
+ */
+static unsigned long SA5_fifo_full(struct ctlr_info *h)
+{
+       if (h->commands_outstanding >= h->max_commands)
+               return 1;
+       else
+               return 0;
+
+}
+/*
+ *   returns value read from hardware.
+ *     returns FIFO_EMPTY if there is nothing to read
+ */
+static unsigned long SA5_completed(struct ctlr_info *h)
+{
+       unsigned long register_value
+               = readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
+
+       if (register_value != FIFO_EMPTY)
+               h->commands_outstanding--;
+
+#ifdef HPSA_DEBUG
+       if (register_value != FIFO_EMPTY)
+               printk(KERN_INFO "hpsa:  Read %lx back from board\n",
+                       register_value);
+       else
+               printk(KERN_INFO "hpsa:  FIFO Empty read\n");
+#endif
+
+       return register_value;
+}
+/*
+ *     Returns true if an interrupt is pending..
+ */
+static unsigned long SA5_intr_pending(struct ctlr_info *h)
+{
+       unsigned long register_value  =
+               readl(h->vaddr + SA5_INTR_STATUS);
+#ifdef HPSA_DEBUG
+       printk(KERN_INFO "hpsa: intr_pending %lx\n", register_value);
+#endif  /* HPSA_DEBUG */
+       if (register_value &  SA5_INTR_PENDING)
+               return  1;
+       return 0 ;
+}
+
+
+static struct access_method SA5_access = {
+       SA5_submit_command,
+       SA5_intr_mask,
+       SA5_fifo_full,
+       SA5_intr_pending,
+       SA5_completed,
+};
+
+struct board_type {
+       __u32   board_id;
+       char    *product_name;
+       struct access_method *access;
+};
+
+
+/* end of old hpsa_scsi.h file */
+
+#endif /* HPSA_H */
+
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
new file mode 100644 (file)
index 0000000..12d7138
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; version 2 of the License.
+ *
+ *    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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+#ifndef HPSA_CMD_H
+#define HPSA_CMD_H
+
+/* general boundary defintions */
+#define SENSEINFOBYTES          32 /* may vary between hbas */
+#define MAXSGENTRIES            31
+#define MAXREPLYQS              256
+
+/* Command Status value */
+#define CMD_SUCCESS             0x0000
+#define CMD_TARGET_STATUS       0x0001
+#define CMD_DATA_UNDERRUN       0x0002
+#define CMD_DATA_OVERRUN        0x0003
+#define CMD_INVALID             0x0004
+#define CMD_PROTOCOL_ERR        0x0005
+#define CMD_HARDWARE_ERR        0x0006
+#define CMD_CONNECTION_LOST     0x0007
+#define CMD_ABORTED             0x0008
+#define CMD_ABORT_FAILED        0x0009
+#define CMD_UNSOLICITED_ABORT   0x000A
+#define CMD_TIMEOUT             0x000B
+#define CMD_UNABORTABLE                0x000C
+
+/* Unit Attentions ASC's as defined for the MSA2012sa */
+#define POWER_OR_RESET                 0x29
+#define STATE_CHANGED                  0x2a
+#define UNIT_ATTENTION_CLEARED         0x2f
+#define LUN_FAILED                     0x3e
+#define REPORT_LUNS_CHANGED            0x3f
+
+/* Unit Attentions ASCQ's as defined for the MSA2012sa */
+
+       /* These ASCQ's defined for ASC = POWER_OR_RESET */
+#define POWER_ON_RESET                 0x00
+#define POWER_ON_REBOOT                        0x01
+#define SCSI_BUS_RESET                 0x02
+#define MSA_TARGET_RESET               0x03
+#define CONTROLLER_FAILOVER            0x04
+#define TRANSCEIVER_SE                 0x05
+#define TRANSCEIVER_LVD                        0x06
+
+       /* These ASCQ's defined for ASC = STATE_CHANGED */
+#define RESERVATION_PREEMPTED          0x03
+#define ASYM_ACCESS_CHANGED            0x06
+#define LUN_CAPACITY_CHANGED           0x09
+
+/* transfer direction */
+#define XFER_NONE               0x00
+#define XFER_WRITE              0x01
+#define XFER_READ               0x02
+#define XFER_RSVD               0x03
+
+/* task attribute */
+#define ATTR_UNTAGGED           0x00
+#define ATTR_SIMPLE             0x04
+#define ATTR_HEADOFQUEUE        0x05
+#define ATTR_ORDERED            0x06
+#define ATTR_ACA                0x07
+
+/* cdb type */
+#define TYPE_CMD                               0x00
+#define TYPE_MSG                               0x01
+
+/* config space register offsets */
+#define CFG_VENDORID            0x00
+#define CFG_DEVICEID            0x02
+#define CFG_I2OBAR              0x10
+#define CFG_MEM1BAR             0x14
+
+/* i2o space register offsets */
+#define I2O_IBDB_SET            0x20
+#define I2O_IBDB_CLEAR          0x70
+#define I2O_INT_STATUS          0x30
+#define I2O_INT_MASK            0x34
+#define I2O_IBPOST_Q            0x40
+#define I2O_OBPOST_Q            0x44
+#define I2O_DMA1_CFG           0x214
+
+/* Configuration Table */
+#define CFGTBL_ChangeReq        0x00000001l
+#define CFGTBL_AccCmds          0x00000001l
+
+#define CFGTBL_Trans_Simple     0x00000002l
+
+#define CFGTBL_BusType_Ultra2   0x00000001l
+#define CFGTBL_BusType_Ultra3   0x00000002l
+#define CFGTBL_BusType_Fibre1G  0x00000100l
+#define CFGTBL_BusType_Fibre2G  0x00000200l
+struct vals32 {
+       __u32   lower;
+       __u32   upper;
+};
+
+union u64bit {
+       struct vals32 val32;
+       __u64 val;
+};
+
+/* FIXME this is a per controller value (barf!) */
+#define HPSA_MAX_TARGETS_PER_CTLR 16
+#define HPSA_MAX_LUN 256
+#define HPSA_MAX_PHYS_LUN 1024
+
+/* SCSI-3 Commands */
+#pragma pack(1)
+
+#define HPSA_INQUIRY 0x12
+struct InquiryData {
+       __u8 data_byte[36];
+};
+
+#define HPSA_REPORT_LOG 0xc2    /* Report Logical LUNs */
+#define HPSA_REPORT_PHYS 0xc3   /* Report Physical LUNs */
+struct ReportLUNdata {
+       __u8 LUNListLength[4];
+       __u32 reserved;
+       __u8 LUN[HPSA_MAX_LUN][8];
+};
+
+struct ReportExtendedLUNdata {
+       __u8 LUNListLength[4];
+       __u8 extended_response_flag;
+       __u8 reserved[3];
+       __u8 LUN[HPSA_MAX_LUN][24];
+};
+
+struct SenseSubsystem_info {
+       __u8 reserved[36];
+       __u8 portname[8];
+       __u8 reserved1[1108];
+};
+
+#define HPSA_READ_CAPACITY 0x25 /* Read Capacity */
+struct ReadCapdata {
+       __u8 total_size[4];     /* Total size in blocks */
+       __u8 block_size[4];     /* Size of blocks in bytes */
+};
+
+#if 0
+/* 12 byte commands not implemented in firmware yet. */
+#define HPSA_READ      0xa8
+#define HPSA_WRITE     0xaa
+#endif
+
+#define HPSA_READ   0x28    /* Read(10) */
+#define HPSA_WRITE  0x2a    /* Write(10) */
+
+/* BMIC commands */
+#define BMIC_READ 0x26
+#define BMIC_WRITE 0x27
+#define BMIC_CACHE_FLUSH 0xc2
+#define HPSA_CACHE_FLUSH 0x01  /* C2 was already being used by HPSA */
+
+/* Command List Structure */
+union SCSI3Addr {
+       struct {
+               __u8 Dev;
+               __u8 Bus:6;
+               __u8 Mode:2;        /* b00 */
+       } PeripDev;
+       struct {
+               __u8 DevLSB;
+               __u8 DevMSB:6;
+               __u8 Mode:2;        /* b01 */
+       } LogDev;
+       struct {
+               __u8 Dev:5;
+               __u8 Bus:3;
+               __u8 Targ:6;
+               __u8 Mode:2;        /* b10 */
+       } LogUnit;
+};
+
+struct PhysDevAddr {
+       __u32             TargetId:24;
+       __u32             Bus:6;
+       __u32             Mode:2;
+       /* 2 level target device addr */
+       union SCSI3Addr  Target[2];
+};
+
+struct LogDevAddr {
+       __u32            VolId:30;
+       __u32            Mode:2;
+       __u8             reserved[4];
+};
+
+union LUNAddr {
+       __u8               LunAddrBytes[8];
+       union SCSI3Addr    SCSI3Lun[4];
+       struct PhysDevAddr PhysDev;
+       struct LogDevAddr  LogDev;
+};
+
+struct CommandListHeader {
+       __u8              ReplyQueue;
+       __u8              SGList;
+       __u16             SGTotal;
+       struct vals32     Tag;
+       union LUNAddr     LUN;
+};
+
+struct RequestBlock {
+       __u8   CDBLen;
+       struct {
+               __u8 Type:3;
+               __u8 Attribute:3;
+               __u8 Direction:2;
+       } Type;
+       __u16  Timeout;
+       __u8   CDB[16];
+};
+
+struct ErrDescriptor {
+       struct vals32 Addr;
+       __u32  Len;
+};
+
+struct SGDescriptor {
+       struct vals32 Addr;
+       __u32  Len;
+       __u32  Ext;
+};
+
+union MoreErrInfo {
+       struct {
+               __u8  Reserved[3];
+               __u8  Type;
+               __u32 ErrorInfo;
+       } Common_Info;
+       struct {
+               __u8  Reserved[2];
+               __u8  offense_size; /* size of offending entry */
+               __u8  offense_num;  /* byte # of offense 0-base */
+               __u32 offense_value;
+       } Invalid_Cmd;
+};
+struct ErrorInfo {
+       __u8               ScsiStatus;
+       __u8               SenseLen;
+       __u16              CommandStatus;
+       __u32              ResidualCnt;
+       union MoreErrInfo  MoreErrInfo;
+       __u8               SenseInfo[SENSEINFOBYTES];
+};
+/* Command types */
+#define CMD_IOCTL_PEND  0x01
+#define CMD_SCSI       0x03
+
+struct ctlr_info; /* defined in hpsa.h */
+/* The size of this structure needs to be divisible by 8
+ * od on all architectures, because the controller uses 2
+ * lower bits of the address, and the driver uses 1 lower
+ * bit (3 bits total.)
+ */
+struct CommandList {
+       struct CommandListHeader Header;
+       struct RequestBlock      Request;
+       struct ErrDescriptor     ErrDesc;
+       struct SGDescriptor      SG[MAXSGENTRIES];
+       /* information associated with the command */
+       __u32                      busaddr; /* physical addr of this record */
+       struct ErrorInfo *err_info; /* pointer to the allocated mem */
+       struct ctlr_info           *h;
+       int                        cmd_type;
+       long                       cmdindex;
+       struct hlist_node list;
+       struct CommandList *prev;
+       struct CommandList *next;
+       struct request *rq;
+       struct completion *waiting;
+       int      retry_count;
+       void   *scsi_cmd;
+};
+
+/* Configuration Table Structure */
+struct HostWrite {
+       __u32 TransportRequest;
+       __u32 Reserved;
+       __u32 CoalIntDelay;
+       __u32 CoalIntCount;
+};
+
+struct CfgTable {
+       __u8             Signature[4];
+       __u32            SpecValence;
+       __u32            TransportSupport;
+       __u32            TransportActive;
+       struct HostWrite HostWrite;
+       __u32            CmdsOutMax;
+       __u32            BusTypes;
+       __u32            Reserved;
+       __u8             ServerName[16];
+       __u32            HeartBeat;
+       __u32            SCSI_Prefetch;
+};
+
+struct hpsa_pci_info {
+       unsigned char   bus;
+       unsigned char   dev_fn;
+       unsigned short  domain;
+       __u32           board_id;
+};
+
+#pragma pack()
+#endif /* HPSA_CMD_H */
index 8643f50..9e52d16 100644 (file)
@@ -6521,6 +6521,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
        int rc;
 
        ENTER;
+       ioa_cfg->pdev->state_saved = true;
        rc = pci_restore_state(ioa_cfg->pdev);
 
        if (rc != PCIBIOS_SUCCESSFUL) {
index c4b58d0..881d5df 100644 (file)
@@ -68,18 +68,20 @@ struct kmem_cache *scsi_pkt_cachep;
 
 /**
  * struct fc_fcp_internal - FCP layer internal data
- * @scsi_pkt_pool:  Memory pool to draw FCP packets from
+ * @scsi_pkt_pool: Memory pool to draw FCP packets from
+ * @scsi_queue_lock: Protects the scsi_pkt_queue
  * @scsi_pkt_queue: Current FCP packets
  * @last_can_queue_ramp_down_time: ramp down time
  * @last_can_queue_ramp_up_time: ramp up time
  * @max_can_queue: max can_queue size
  */
 struct fc_fcp_internal {
-       mempool_t        *scsi_pkt_pool;
-       struct list_head scsi_pkt_queue;
-       unsigned long last_can_queue_ramp_down_time;
-       unsigned long last_can_queue_ramp_up_time;
-       int max_can_queue;
+       mempool_t               *scsi_pkt_pool;
+       spinlock_t              scsi_queue_lock;
+       struct list_head        scsi_pkt_queue;
+       unsigned long           last_can_queue_ramp_down_time;
+       unsigned long           last_can_queue_ramp_up_time;
+       int                     max_can_queue;
 };
 
 #define fc_get_scsi_internal(x)        ((struct fc_fcp_internal *)(x)->scsi_priv)
@@ -410,12 +412,14 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
        unsigned long flags;
 
        fp = fc_frame_alloc(lport, len);
-       if (!fp) {
-               spin_lock_irqsave(lport->host->host_lock, flags);
-               fc_fcp_can_queue_ramp_down(lport);
-               spin_unlock_irqrestore(lport->host->host_lock, flags);
-       }
-       return fp;
+       if (likely(fp))
+               return fp;
+
+       /* error case */
+       spin_lock_irqsave(lport->host->host_lock, flags);
+       fc_fcp_can_queue_ramp_down(lport);
+       spin_unlock_irqrestore(lport->host->host_lock, flags);
+       return NULL;
 }
 
 /**
@@ -990,7 +994,7 @@ static void fc_fcp_cleanup_each_cmd(struct fc_lport *lport, unsigned int id,
        struct scsi_cmnd *sc_cmd;
        unsigned long flags;
 
-       spin_lock_irqsave(lport->host->host_lock, flags);
+       spin_lock_irqsave(&si->scsi_queue_lock, flags);
 restart:
        list_for_each_entry(fsp, &si->scsi_pkt_queue, list) {
                sc_cmd = fsp->cmd;
@@ -1001,7 +1005,7 @@ restart:
                        continue;
 
                fc_fcp_pkt_hold(fsp);
-               spin_unlock_irqrestore(lport->host->host_lock, flags);
+               spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 
                if (!fc_fcp_lock_pkt(fsp)) {
                        fc_fcp_cleanup_cmd(fsp, error);
@@ -1010,14 +1014,14 @@ restart:
                }
 
                fc_fcp_pkt_release(fsp);
-               spin_lock_irqsave(lport->host->host_lock, flags);
+               spin_lock_irqsave(&si->scsi_queue_lock, flags);
                /*
                 * while we dropped the lock multiple pkts could
                 * have been released, so we have to start over.
                 */
                goto restart;
        }
-       spin_unlock_irqrestore(lport->host->host_lock, flags);
+       spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 }
 
 /**
@@ -1035,11 +1039,12 @@ static void fc_fcp_abort_io(struct fc_lport *lport)
  * @fsp:   The FCP packet to send
  *
  * Return:  Zero for success and -1 for failure
- * Locks:   Called with the host lock and irqs disabled.
+ * Locks:   Called without locks held
  */
 static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
 {
        struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
+       unsigned long flags;
        int rc;
 
        fsp->cmd->SCp.ptr = (char *)fsp;
@@ -1049,13 +1054,16 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
        int_to_scsilun(fsp->cmd->device->lun,
                       (struct scsi_lun *)fsp->cdb_cmd.fc_lun);
        memcpy(fsp->cdb_cmd.fc_cdb, fsp->cmd->cmnd, fsp->cmd->cmd_len);
-       list_add_tail(&fsp->list, &si->scsi_pkt_queue);
 
-       spin_unlock_irq(lport->host->host_lock);
+       spin_lock_irqsave(&si->scsi_queue_lock, flags);
+       list_add_tail(&fsp->list, &si->scsi_pkt_queue);
+       spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
        rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv);
-       spin_lock_irq(lport->host->host_lock);
-       if (rc)
+       if (unlikely(rc)) {
+               spin_lock_irqsave(&si->scsi_queue_lock, flags);
                list_del(&fsp->list);
+               spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
+       }
 
        return rc;
 }
@@ -1752,6 +1760,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
        struct fcoe_dev_stats *stats;
 
        lport = shost_priv(sc_cmd->device->host);
+       spin_unlock_irq(lport->host->host_lock);
 
        rval = fc_remote_port_chkready(rport);
        if (rval) {
@@ -1834,6 +1843,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
                rc = SCSI_MLQUEUE_HOST_BUSY;
        }
 out:
+       spin_lock_irq(lport->host->host_lock);
        return rc;
 }
 EXPORT_SYMBOL(fc_queuecommand);
@@ -1864,11 +1874,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
 
        lport = fsp->lp;
        si = fc_get_scsi_internal(lport);
-       spin_lock_irqsave(lport->host->host_lock, flags);
-       if (!fsp->cmd) {
-               spin_unlock_irqrestore(lport->host->host_lock, flags);
+       if (!fsp->cmd)
                return;
-       }
 
        /*
         * if can_queue ramp down is done then try can_queue ramp up
@@ -1880,10 +1887,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
        sc_cmd = fsp->cmd;
        fsp->cmd = NULL;
 
-       if (!sc_cmd->SCp.ptr) {
-               spin_unlock_irqrestore(lport->host->host_lock, flags);
+       if (!sc_cmd->SCp.ptr)
                return;
-       }
 
        CMD_SCSI_STATUS(sc_cmd) = fsp->cdb_status;
        switch (fsp->status_code) {
@@ -1945,10 +1950,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
                break;
        }
 
+       spin_lock_irqsave(&si->scsi_queue_lock, flags);
        list_del(&fsp->list);
+       spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
        sc_cmd->SCp.ptr = NULL;
        sc_cmd->scsi_done(sc_cmd);
-       spin_unlock_irqrestore(lport->host->host_lock, flags);
 
        /* release ref from initial allocation in queue command */
        fc_fcp_pkt_release(fsp);
@@ -2216,6 +2222,7 @@ int fc_fcp_init(struct fc_lport *lport)
        lport->scsi_priv = si;
        si->max_can_queue = lport->host->can_queue;
        INIT_LIST_HEAD(&si->scsi_pkt_queue);
+       spin_lock_init(&si->scsi_queue_lock);
 
        si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep);
        if (!si->scsi_pkt_pool) {
index 74338c8..0b16502 100644 (file)
@@ -537,7 +537,9 @@ int fc_fabric_login(struct fc_lport *lport)
        int rc = -1;
 
        mutex_lock(&lport->lp_mutex);
-       if (lport->state == LPORT_ST_DISABLED) {
+       if (lport->state == LPORT_ST_DISABLED ||
+           lport->state == LPORT_ST_LOGO) {
+               fc_lport_state_enter(lport, LPORT_ST_RESET);
                fc_lport_enter_reset(lport);
                rc = 0;
        }
@@ -967,6 +969,9 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
        FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
                     fc_lport_state(lport));
 
+       if (lport->state == LPORT_ST_DISABLED || lport->state == LPORT_ST_LOGO)
+               return;
+
        if (lport->vport) {
                if (lport->link_up)
                        fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);
index 35ca0e7..0230052 100644 (file)
@@ -310,6 +310,7 @@ static void fc_rport_work(struct work_struct *work)
                                restart = 1;
                        else
                                list_del(&rdata->peers);
+                       rdata->event = RPORT_EV_NONE;
                        mutex_unlock(&rdata->rp_mutex);
                        mutex_unlock(&lport->disc.disc_mutex);
                }
index 226920d..d4da6bd 100644 (file)
@@ -4506,9 +4506,13 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
                pdev = phba->pcidev;
 
        /* Set the device DMA mask size */
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+        || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+                || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
                        return error;
+               }
+       }
 
        /* Get the bus address of Bar0 and Bar2 and the number of bytes
         * required by each mapping.
@@ -6021,9 +6025,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
                pdev = phba->pcidev;
 
        /* Set the device DMA mask size */
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+        || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+                || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
                        return error;
+               }
+       }
 
        /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
         * number of bytes required by each mapping. They are actually
index 134c63e..99ff99e 100644 (file)
@@ -2501,7 +2501,9 @@ static int megasas_init_mfi(struct megasas_instance *instance)
                instance->base_addr = pci_resource_start(instance->pdev, 0);
        }
 
-       if (pci_request_regions(instance->pdev, "megasas: LSI")) {
+       if (pci_request_selected_regions(instance->pdev,
+               pci_select_bars(instance->pdev, IORESOURCE_MEM),
+               "megasas: LSI")) {
                printk(KERN_DEBUG "megasas: IO memory region busy!\n");
                return -EBUSY;
        }
@@ -2642,7 +2644,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
        iounmap(instance->reg_set);
 
       fail_ioremap:
-       pci_release_regions(instance->pdev);
+       pci_release_selected_regions(instance->pdev,
+               pci_select_bars(instance->pdev, IORESOURCE_MEM));
 
        return -EINVAL;
 }
@@ -2662,7 +2665,8 @@ static void megasas_release_mfi(struct megasas_instance *instance)
 
        iounmap(instance->reg_set);
 
-       pci_release_regions(instance->pdev);
+       pci_release_selected_regions(instance->pdev,
+               pci_select_bars(instance->pdev, IORESOURCE_MEM));
 }
 
 /**
@@ -2971,7 +2975,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /*
         * PCI prepping: enable device set bus mastering and dma mask
         */
-       rval = pci_enable_device(pdev);
+       rval = pci_enable_device_mem(pdev);
 
        if (rval) {
                return rval;
@@ -3276,7 +3280,7 @@ megasas_resume(struct pci_dev *pdev)
        /*
         * PCI prepping: enable device set bus mastering and dma mask
         */
-       rval = pci_enable_device(pdev);
+       rval = pci_enable_device_mem(pdev);
 
        if (rval) {
                printk(KERN_ERR "megasas: Enable device failed\n");
index 6422e25..89d0240 100644 (file)
@@ -3583,6 +3583,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
        mutex_init(&ioc->transport_cmds.mutex);
 
+       /* scsih internal command bits */
+       ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
+       mutex_init(&ioc->scsih_cmds.mutex);
+
        /* task management internal command bits */
        ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
index c790d45..cae6b2c 100644 (file)
@@ -657,6 +657,7 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
        { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
        { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
        { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
+       { PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
 
        { }     /* terminate list */
 };
index 950202a..2422347 100644 (file)
@@ -432,30 +432,23 @@ static void _osd_free_seg(struct osd_request *or __unused,
        seg->alloc_size = 0;
 }
 
-static void _put_request(struct request *rq , bool is_async)
+static void _put_request(struct request *rq)
 {
-       if (is_async) {
-               WARN_ON(rq->bio);
-               __blk_put_request(rq->q, rq);
-       } else {
-               /*
-                * If osd_finalize_request() was called but the request was not
-                * executed through the block layer, then we must release BIOs.
-                * TODO: Keep error code in or->async_error. Need to audit all
-                *       code paths.
-                */
-               if (unlikely(rq->bio))
-                       blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
-               else
-                       blk_put_request(rq);
-       }
+       /*
+        * If osd_finalize_request() was called but the request was not
+        * executed through the block layer, then we must release BIOs.
+        * TODO: Keep error code in or->async_error. Need to audit all
+        *       code paths.
+        */
+       if (unlikely(rq->bio))
+               blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
+       else
+               blk_put_request(rq);
 }
 
 void osd_end_request(struct osd_request *or)
 {
        struct request *rq = or->request;
-       /* IMPORTANT: make sure this agrees with osd_execute_request_async */
-       bool is_async = (or->request->end_io_data == or);
 
        _osd_free_seg(or, &or->set_attr);
        _osd_free_seg(or, &or->enc_get_attr);
@@ -463,20 +456,34 @@ void osd_end_request(struct osd_request *or)
 
        if (rq) {
                if (rq->next_rq) {
-                       _put_request(rq->next_rq, is_async);
+                       _put_request(rq->next_rq);
                        rq->next_rq = NULL;
                }
 
-               _put_request(rq, is_async);
+               _put_request(rq);
        }
        _osd_request_free(or);
 }
 EXPORT_SYMBOL(osd_end_request);
 
+static void _set_error_resid(struct osd_request *or, struct request *req,
+                            int error)
+{
+       or->async_error = error;
+       or->req_errors = req->errors ? : error;
+       or->sense_len = req->sense_len;
+       if (or->out.req)
+               or->out.residual = or->out.req->resid_len;
+       if (or->in.req)
+               or->in.residual = or->in.req->resid_len;
+}
+
 int osd_execute_request(struct osd_request *or)
 {
-       return or->async_error =
-                       blk_execute_rq(or->request->q, NULL, or->request, 0);
+       int error = blk_execute_rq(or->request->q, NULL, or->request, 0);
+
+       _set_error_resid(or, or->request, error);
+       return error;
 }
 EXPORT_SYMBOL(osd_execute_request);
 
@@ -484,15 +491,17 @@ static void osd_request_async_done(struct request *req, int error)
 {
        struct osd_request *or = req->end_io_data;
 
-       or->async_error = error;
-
-       if (unlikely(error)) {
-               OSD_DEBUG("osd_request_async_done error recieved %d "
-                         "errors 0x%x\n", error, req->errors);
-               if (!req->errors) /* don't miss out on this one */
-                       req->errors = error;
+       _set_error_resid(or, req, error);
+       if (req->next_rq) {
+               __blk_put_request(req->q, req->next_rq);
+               req->next_rq = NULL;
        }
 
+       __blk_put_request(req->q, req);
+       or->request = NULL;
+       or->in.req = NULL;
+       or->out.req = NULL;
+
        if (or->async_done)
                or->async_done(or, or->async_private);
        else
@@ -1489,21 +1498,18 @@ int osd_req_decode_sense_full(struct osd_request *or,
 #endif
        int ret;
 
-       if (likely(!or->request->errors)) {
-               osi->out_resid = 0;
-               osi->in_resid = 0;
+       if (likely(!or->req_errors))
                return 0;
-       }
 
        osi = osi ? : &local_osi;
        memset(osi, 0, sizeof(*osi));
 
-       ssdb = or->request->sense;
-       sense_len = or->request->sense_len;
+       ssdb = (typeof(ssdb))or->sense;
+       sense_len = or->sense_len;
        if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
                OSD_ERR("Block-layer returned error(0x%x) but "
                        "sense_len(%u) || key(%d) is empty\n",
-                       or->request->errors, sense_len, ssdb->sense_key);
+                       or->req_errors, sense_len, ssdb->sense_key);
                goto analyze;
        }
 
@@ -1525,7 +1531,7 @@ int osd_req_decode_sense_full(struct osd_request *or,
                        "additional_code=0x%x async_error=%d errors=0x%x\n",
                        osi->key, original_sense_len, sense_len,
                        osi->additional_code, or->async_error,
-                       or->request->errors);
+                       or->req_errors);
 
        if (original_sense_len < sense_len)
                sense_len = original_sense_len;
@@ -1695,10 +1701,10 @@ analyze:
                ret = -EIO;
        }
 
-       if (or->out.req)
-               osi->out_resid = or->out.req->resid_len ?: or->out.total_bytes;
-       if (or->in.req)
-               osi->in_resid = or->in.req->resid_len ?: or->in.total_bytes;
+       if (!or->out.residual)
+               or->out.residual = or->out.total_bytes;
+       if (!or->in.residual)
+               or->in.residual = or->in.total_bytes;
 
        return ret;
 }
index 22644de..63ad4aa 100644 (file)
 #define HEADER_LEN                     28
 #define SIZE_OFFSET                    16
 
-struct pm8001_ioctl_payload {
-       u32     signature;
-       u16     major_function;
-       u16     minor_function;
-       u16     length;
-       u16     status;
-       u16     offset;
-       u16     id;
-       u8      func_specific[1];
-};
 
 #define FLASH_OK                        0x000000
 #define FAIL_OPEN_BIOS_FILE             0x000100
index a3de306..9b44c6f 100644 (file)
@@ -373,10 +373,7 @@ static int bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue)
 static void __devinit
 mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
 {
-       u32 offset;
-       u32 value;
-       u32 i, j;
-       u32 bit_cnt;
+       u32 value, offset, i;
 
 #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000
 #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000
@@ -392,55 +389,35 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
     */
        if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR))
                return;
-       /* set SSC bit of PHY 0 - 3 */
+
        for (i = 0; i < 4; i++) {
                offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i;
-               value = pm8001_cr32(pm8001_ha, 2, offset);
-               if (SSCbit) {
-                       value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
-                       value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
-               } else {
-                       value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
-                       value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
-               }
-               bit_cnt = 0;
-               for (j = 0; j < 31; j++)
-                       if ((value >> j) & 0x00000001)
-                               bit_cnt++;
-               if (bit_cnt % 2)
-                       value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
-               else
-                       value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
-
-               pm8001_cw32(pm8001_ha, 2, offset, value);
+               pm8001_cw32(pm8001_ha, 2, offset, 0x80001501);
        }
-
        /* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */
        if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR))
                return;
-
-       /* set SSC bit of PHY 4 - 7 */
        for (i = 4; i < 8; i++) {
                offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4);
-               value = pm8001_cr32(pm8001_ha, 2, offset);
-               if (SSCbit) {
-                       value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
-                       value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
-               } else {
-                       value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
-                       value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
-               }
-               bit_cnt = 0;
-               for (j = 0; j < 31; j++)
-                       if ((value >> j) & 0x00000001)
-                               bit_cnt++;
-               if (bit_cnt % 2)
-                       value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
-               else
-                       value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
-
-               pm8001_cw32(pm8001_ha, 2, offset, value);
+               pm8001_cw32(pm8001_ha, 2, offset, 0x80001501);
        }
+       /*************************************************************
+       Change the SSC upspreading value to 0x0 so that upspreading is disabled.
+       Device MABC SMOD0 Controls
+       Address: (via MEMBASE-III):
+       Using shifted destination address 0x0_0000: with Offset 0xD8
+
+       31:28 R/W Reserved Do not change
+       27:24 R/W SAS_SMOD_SPRDUP 0000
+       23:20 R/W SAS_SMOD_SPRDDN 0000
+       19:0  R/W  Reserved Do not change
+       Upon power-up this register will read as 0x8990c016,
+       and I would like you to change the SAS_SMOD_SPRDUP bits to 0b0000
+       so that the written value will be 0x8090c016.
+       This will ensure only down-spreading SSC is enabled on the SPC.
+       *************************************************************/
+       value = pm8001_cr32(pm8001_ha, 2, 0xd8);
+       pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016);
 
        /*set the shifted destination address to 0x0 to avoid error operation */
        bar4_shift(pm8001_ha, 0x0);
@@ -1901,7 +1878,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        struct sas_task *t;
        struct pm8001_ccb_info *ccb;
-       unsigned long flags;
+       unsigned long flags = 0;
        u32 param;
        u32 status;
        u32 tag;
@@ -2040,7 +2017,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/*in order to force CPU ordering*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2058,7 +2037,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/*ditto*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2084,7 +2065,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/* ditto*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2149,7 +2132,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/*ditto*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2171,7 +2156,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/*ditto*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2200,11 +2187,20 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        " resp 0x%x stat 0x%x but aborted by upper layer!\n",
                        t, status, ts->resp, ts->stat));
                pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-       } else {
+       } else if (t->uldd_task) {
                spin_unlock_irqrestore(&t->task_state_lock, flags);
                pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                mb();/* ditto */
+               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                t->task_done(t);
+               spin_lock_irqsave(&pm8001_ha->lock, flags);
+       } else if (!t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/*ditto*/
+               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+               t->task_done(t);
+               spin_lock_irqsave(&pm8001_ha->lock, flags);
        }
 }
 
@@ -2212,7 +2208,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 {
        struct sas_task *t;
-       unsigned long flags;
+       unsigned long flags = 0;
        struct task_status_struct *ts;
        struct pm8001_ccb_info *ccb;
        struct pm8001_device *pm8001_dev;
@@ -2292,7 +2288,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
                        ts->stat = SAS_QUEUE_FULL;
                        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
                        mb();/*ditto*/
+                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                        t->task_done(t);
+                       spin_lock_irqsave(&pm8001_ha->lock, flags);
                        return;
                }
                break;
@@ -2401,11 +2399,20 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
                        " resp 0x%x stat 0x%x but aborted by upper layer!\n",
                        t, event, ts->resp, ts->stat));
                pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-       } else {
+       } else if (t->uldd_task) {
                spin_unlock_irqrestore(&t->task_state_lock, flags);
                pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-               mb();/* in order to force CPU ordering */
+               mb();/* ditto */
+               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                t->task_done(t);
+               spin_lock_irqsave(&pm8001_ha->lock, flags);
+       } else if (!t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/*ditto*/
+               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+               t->task_done(t);
+               spin_lock_irqsave(&pm8001_ha->lock, flags);
        }
 }
 
@@ -2876,15 +2883,20 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
        u8 link_rate =
                (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
+       u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
        u8 phy_id =
                (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
+       u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
+       u8 portstate = (u8)(npip_portstate & 0x0000000F);
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
        struct sas_ha_struct *sas_ha = pm8001_ha->sas;
        struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
-
+       port->port_state =  portstate;
        PM8001_MSG_DBG(pm8001_ha,
-               pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));
+               pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
+               port_id, phy_id));
 
        switch (deviceType) {
        case SAS_PHY_UNUSED:
@@ -2895,16 +2907,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
                pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
                        PHY_NOTIFY_ENABLE_SPINUP);
+               port->port_attached = 1;
                get_lrate_mode(phy, link_rate);
                break;
        case SAS_EDGE_EXPANDER_DEVICE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("expander device.\n"));
+               port->port_attached = 1;
                get_lrate_mode(phy, link_rate);
                break;
        case SAS_FANOUT_EXPANDER_DEVICE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("fanout expander device.\n"));
+               port->port_attached = 1;
                get_lrate_mode(phy, link_rate);
                break;
        default:
@@ -2946,11 +2961,20 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
        u8 link_rate =
                (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
+       u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
        u8 phy_id =
                (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
+       u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
+       u8 portstate = (u8)(npip_portstate & 0x0000000F);
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
        struct sas_ha_struct *sas_ha = pm8001_ha->sas;
        struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
        unsigned long flags;
+       PM8001_MSG_DBG(pm8001_ha,
+               pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
+               " phy id = %d\n", port_id, phy_id));
+       port->port_state =  portstate;
+       port->port_attached = 1;
        get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
        phy->phy_attached = 1;
@@ -2984,7 +3008,13 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
                (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
        u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
        u8 portstate = (u8)(npip_portstate & 0x0000000F);
-
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+       port->port_state =  portstate;
+       phy->phy_type = 0;
+       phy->identify.device_type = 0;
+       phy->phy_attached = 0;
+       memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
        switch (portstate) {
        case PORT_VALID:
                break;
@@ -2993,26 +3023,30 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
                        pm8001_printk(" PortInvalid portID %d \n", port_id));
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk(" Last phy Down and port invalid\n"));
+               port->port_attached = 0;
                pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
                        port_id, phy_id, 0, 0);
                break;
        case PORT_IN_RESET:
                PM8001_MSG_DBG(pm8001_ha,
-                       pm8001_printk(" PortInReset portID %d \n", port_id));
+                       pm8001_printk(" Port In Reset portID %d \n", port_id));
                break;
        case PORT_NOT_ESTABLISHED:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
+               port->port_attached = 0;
                break;
        case PORT_LOSTCOMM:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk(" Last phy Down and port invalid\n"));
+               port->port_attached = 0;
                pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
                        port_id, phy_id, 0, 0);
                break;
        default:
+               port->port_attached = 0;
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk(" phy Down and(default) = %x\n",
                        portstate));
@@ -3770,7 +3804,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
        u32 opc = OPC_INB_SSPINIIOSTART;
        memset(&ssp_cmd, 0, sizeof(ssp_cmd));
        memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
-       ssp_cmd.dir_m_tlr = data_dir_flags[task->data_dir] << 8 | 0x0;/*0 for
+       ssp_cmd.dir_m_tlr =
+               cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);/*0 for
        SAS 1.1 compatible TLR*/
        ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);
        ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
@@ -3841,7 +3876,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
                }
        }
        if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
-               ncg_tag = cpu_to_le32(hdr_tag);
+               ncg_tag = hdr_tag;
        dir = data_dir_flags[task->data_dir] << 8;
        sata_cmd.tag = cpu_to_le32(tag);
        sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
@@ -3986,7 +4021,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
                ((stp_sspsmp_sata & 0x03) * 0x10000000));
        payload.firstburstsize_ITNexustimeout =
                cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
-       memcpy(&payload.sas_addr_hi, pm8001_dev->sas_device->sas_addr,
+       memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
                SAS_ADDR_SIZE);
        rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
        return rc;
@@ -4027,7 +4062,7 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
        struct inbound_queue_table *circularQ;
        int ret;
        u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
-       memset((u8 *)&payload, 0, sizeof(payload));
+       memset(&payload, 0, sizeof(payload));
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
        payload.tag = 1;
        payload.phyop_phyid =
index 96e4daa..833a520 100644 (file)
@@ -242,8 +242,7 @@ struct reg_dev_req {
        __le32  phyid_portid;
        __le32  dtype_dlr_retry;
        __le32  firstburstsize_ITNexustimeout;
-       u32     sas_addr_hi;
-       u32     sas_addr_low;
+       u8      sas_addr[SAS_ADDR_SIZE];
        __le32  upper_device_id;
        u32     reserved[8];
 } __attribute__((packed, aligned(4)));
index 42ebe72..c2f1032 100644 (file)
@@ -200,8 +200,13 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
 {
        int i;
        spin_lock_init(&pm8001_ha->lock);
-       for (i = 0; i < pm8001_ha->chip->n_phy; i++)
+       for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
                pm8001_phy_init(pm8001_ha, i);
+               pm8001_ha->port[i].wide_port_phymap = 0;
+               pm8001_ha->port[i].port_attached = 0;
+               pm8001_ha->port[i].port_state = 0;
+               INIT_LIST_HEAD(&pm8001_ha->port[i].list);
+       }
 
        pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
        if (!pm8001_ha->tags)
@@ -511,19 +516,23 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        u8 i;
 #ifdef PM8001_READ_VPD
        DECLARE_COMPLETION_ONSTACK(completion);
+       struct pm8001_ioctl_payload payload;
        pm8001_ha->nvmd_completion = &completion;
-       PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, 0, 0);
+       payload.minor_function = 0;
+       payload.length = 128;
+       payload.func_specific = kzalloc(128, GFP_KERNEL);
+       PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
        wait_for_completion(&completion);
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
                memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr,
                        SAS_ADDR_SIZE);
                PM8001_INIT_DBG(pm8001_ha,
-                       pm8001_printk("phy %d sas_addr = %x \n", i,
-                       (u64)pm8001_ha->phy[i].dev_sas_addr));
+                       pm8001_printk("phy %d sas_addr = %016llx \n", i,
+                       pm8001_ha->phy[i].dev_sas_addr));
        }
 #else
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
-               pm8001_ha->phy[i].dev_sas_addr = 0x500e004010000004ULL;
+               pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL;
                pm8001_ha->phy[i].dev_sas_addr =
                        cpu_to_be64((u64)
                                (*(u64 *)&pm8001_ha->phy[i].dev_sas_addr));
index 1f767a0..7f9c83a 100644 (file)
@@ -329,6 +329,23 @@ int pm8001_slave_configure(struct scsi_device *sdev)
        }
        return 0;
 }
+ /* Find the local port id that's attached to this device */
+static int sas_find_local_port_id(struct domain_device *dev)
+{
+       struct domain_device *pdev = dev->parent;
+
+       /* Directly attached device */
+       if (!pdev)
+               return dev->port->id;
+       while (pdev) {
+               struct domain_device *pdev_p = pdev->parent;
+               if (!pdev_p)
+                       return pdev->port->id;
+               pdev = pdev->parent;
+       }
+       return 0;
+}
+
 /**
   * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
   * @task: the task to be execute.
@@ -346,11 +363,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
        struct domain_device *dev = task->dev;
        struct pm8001_hba_info *pm8001_ha;
        struct pm8001_device *pm8001_dev;
+       struct pm8001_port *port = NULL;
        struct sas_task *t = task;
        struct pm8001_ccb_info *ccb;
        u32 tag = 0xdeadbeef, rc, n_elem = 0;
        u32 n = num;
-       unsigned long flags = 0;
+       unsigned long flags = 0, flags_libsas = 0;
 
        if (!dev->port) {
                struct task_status_struct *tsm = &t->task_status;
@@ -379,6 +397,35 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
                        rc = SAS_PHY_DOWN;
                        goto out_done;
                }
+               port = &pm8001_ha->port[sas_find_local_port_id(dev)];
+               if (!port->port_attached) {
+                       if (sas_protocol_ata(t->task_proto)) {
+                               struct task_status_struct *ts = &t->task_status;
+                               ts->resp = SAS_TASK_UNDELIVERED;
+                               ts->stat = SAS_PHY_DOWN;
+
+                               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+                               spin_unlock_irqrestore(dev->sata_dev.ap->lock,
+                                               flags_libsas);
+                               t->task_done(t);
+                               spin_lock_irqsave(dev->sata_dev.ap->lock,
+                                       flags_libsas);
+                               spin_lock_irqsave(&pm8001_ha->lock, flags);
+                               if (n > 1)
+                                       t = list_entry(t->list.next,
+                                                       struct sas_task, list);
+                               continue;
+                       } else {
+                               struct task_status_struct *ts = &t->task_status;
+                               ts->resp = SAS_TASK_UNDELIVERED;
+                               ts->stat = SAS_PHY_DOWN;
+                               t->task_done(t);
+                               if (n > 1)
+                                       t = list_entry(t->list.next,
+                                                       struct sas_task, list);
+                               continue;
+                       }
+               }
                rc = pm8001_tag_alloc(pm8001_ha, &tag);
                if (rc)
                        goto err_out;
@@ -569,11 +616,11 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
        spin_lock_irqsave(&pm8001_ha->lock, flags);
 
        pm8001_device = pm8001_alloc_dev(pm8001_ha);
-       pm8001_device->sas_device = dev;
        if (!pm8001_device) {
                res = -1;
                goto found_out;
        }
+       pm8001_device->sas_device = dev;
        dev->lldd_dev = pm8001_device;
        pm8001_device->dev_type = dev->dev_type;
        pm8001_device->dcompletion = &completion;
@@ -609,7 +656,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
        wait_for_completion(&completion);
        if (dev->dev_type == SAS_END_DEV)
                msleep(50);
-       pm8001_ha->flags = PM8001F_RUN_TIME ;
+       pm8001_ha->flags |= PM8001F_RUN_TIME ;
        return 0;
 found_out:
        spin_unlock_irqrestore(&pm8001_ha->lock, flags);
@@ -772,7 +819,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
                task->task_done = pm8001_task_done;
                task->timer.data = (unsigned long)task;
                task->timer.function = pm8001_tmf_timedout;
-               task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
+               task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
                add_timer(&task->timer);
 
                res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
@@ -897,6 +944,8 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
 
        if (dev_is_sata(dev)) {
                DECLARE_COMPLETION_ONSTACK(completion_setstate);
+               if (scsi_is_sas_phy_local(phy))
+                       return 0;
                rc = sas_phy_reset(phy, 1);
                msleep(2000);
                rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
index 30f2ede..8e38ca8 100644 (file)
 
 #define DRV_NAME               "pm8001"
 #define DRV_VERSION            "0.1.36"
-#define PM8001_FAIL_LOGGING    0x01 /* libsas EH function logging */
+#define PM8001_FAIL_LOGGING    0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING    0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING    0x04 /* discovery layer logging */
 #define PM8001_IO_LOGGING      0x08 /* I/O path logging */
-#define PM8001_EH_LOGGING      0x10 /* Error message logging */
+#define PM8001_EH_LOGGING      0x10 /* libsas EH function logging*/
 #define PM8001_IOCTL_LOGGING   0x20 /* IOCTL message logging */
 #define PM8001_MSG_LOGGING     0x40 /* misc message logging */
 #define pm8001_printk(format, arg...)  printk(KERN_INFO "%s %d:" format,\
@@ -100,6 +100,7 @@ do {                                                \
 
 #define PM8001_USE_TASKLET
 #define PM8001_USE_MSIX
+#define PM8001_READ_VPD
 
 
 #define DEV_IS_EXPANDER(type)  ((type == EDGE_DEV) || (type == FANOUT_DEV))
@@ -111,7 +112,22 @@ extern const struct pm8001_dispatch pm8001_8001_dispatch;
 struct pm8001_hba_info;
 struct pm8001_ccb_info;
 struct pm8001_device;
-struct pm8001_tmf_task;
+/* define task management IU */
+struct pm8001_tmf_task {
+       u8      tmf;
+       u32     tag_of_task_to_be_managed;
+};
+struct pm8001_ioctl_payload {
+       u32     signature;
+       u16     major_function;
+       u16     minor_function;
+       u16     length;
+       u16     status;
+       u16     offset;
+       u16     id;
+       u8      *func_specific;
+};
+
 struct pm8001_dispatch {
        char *name;
        int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
@@ -164,6 +180,10 @@ struct pm8001_chip_info {
 
 struct pm8001_port {
        struct asd_sas_port     sas_port;
+       u8                      port_attached;
+       u8                      wide_port_phymap;
+       u8                      port_state;
+       struct list_head        list;
 };
 
 struct pm8001_phy {
@@ -386,11 +406,7 @@ struct pm8001_fw_image_header {
        __be32 startup_entry;
 } __attribute__((packed, aligned(4)));
 
-/* define task management IU */
-struct pm8001_tmf_task {
-       u8      tmf;
-       u32     tag_of_task_to_be_managed;
-};
+
 /**
  * FW Flash Update status values
  */
index 34c6b89..e7d2688 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * pmcraid.c -- driver for PMC Sierra MaxRAID controller adapters
  *
- * Written By: PMC Sierra Corporation
+ * Written By: Anil Ravindranath<anil_ravindranath@pmc-sierra.com>
+ *             PMC-Sierra Inc
  *
  * Copyright (C) 2008, 2009 PMC Sierra Inc
  *
@@ -79,7 +80,7 @@ DECLARE_BITMAP(pmcraid_minor, PMCRAID_MAX_ADAPTERS);
 /*
  * Module parameters
  */
-MODULE_AUTHOR("PMC Sierra Corporation, anil_ravindranath@pmc-sierra.com");
+MODULE_AUTHOR("Anil Ravindranath<anil_ravindranath@pmc-sierra.com>");
 MODULE_DESCRIPTION("PMC Sierra MaxRAID Controller Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PMCRAID_DRIVER_VERSION);
@@ -162,10 +163,10 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev)
        spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
        list_for_each_entry(temp, &pinstance->used_res_q, queue) {
 
-               /* do not expose VSETs with order-ids >= 240 */
+               /* do not expose VSETs with order-ids > MAX_VSET_TARGETS */
                if (RES_IS_VSET(temp->cfg_entry)) {
                        target = temp->cfg_entry.unique_flags1;
-                       if (target >= PMCRAID_MAX_VSET_TARGETS)
+                       if (target > PMCRAID_MAX_VSET_TARGETS)
                                continue;
                        bus = PMCRAID_VSET_BUS_ID;
                        lun = 0;
@@ -1210,7 +1211,7 @@ static int pmcraid_expose_resource(struct pmcraid_config_table_entry *cfgte)
        int retval = 0;
 
        if (cfgte->resource_type == RES_TYPE_VSET)
-               retval = ((cfgte->unique_flags1 & 0xFF) < 0xFE);
+               retval = ((cfgte->unique_flags1 & 0x80) == 0);
        else if (cfgte->resource_type == RES_TYPE_GSCSI)
                retval = (RES_BUS(cfgte->resource_address) !=
                                PMCRAID_VIRTUAL_ENCL_BUS_ID);
@@ -1361,6 +1362,7 @@ static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type)
  * Return value:
  *  none
  */
+
 static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
 {
        struct pmcraid_config_table_entry *cfg_entry;
@@ -1368,9 +1370,10 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
        struct pmcraid_cmd *cmd;
        struct pmcraid_cmd *cfgcmd;
        struct pmcraid_resource_entry *res = NULL;
-       u32 new_entry = 1;
        unsigned long lock_flags;
        unsigned long host_lock_flags;
+       u32 new_entry = 1;
+       u32 hidden_entry = 0;
        int rc;
 
        ccn_hcam = (struct pmcraid_hcam_ccn *)pinstance->ccn.hcam;
@@ -1406,9 +1409,15 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
        }
 
        /* If this resource is not going to be added to mid-layer, just notify
-        * applications and return
+        * applications and return. If this notification is about hiding a VSET
+        * resource, check if it was exposed already.
         */
-       if (!pmcraid_expose_resource(cfg_entry))
+       if (pinstance->ccn.hcam->notification_type ==
+           NOTIFICATION_TYPE_ENTRY_CHANGED &&
+           cfg_entry->resource_type == RES_TYPE_VSET &&
+           cfg_entry->unique_flags1 & 0x80) {
+               hidden_entry = 1;
+       } else if (!pmcraid_expose_resource(cfg_entry))
                goto out_notify_apps;
 
        spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
@@ -1424,6 +1433,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
 
        if (new_entry) {
 
+               if (hidden_entry) {
+                       spin_unlock_irqrestore(&pinstance->resource_lock,
+                                               lock_flags);
+                       goto out_notify_apps;
+               }
+
                /* If there are more number of resources than what driver can
                 * manage, do not notify the applications about the CCN. Just
                 * ignore this notifications and re-register the same HCAM
@@ -1454,8 +1469,9 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
                sizeof(struct pmcraid_config_table_entry));
 
        if (pinstance->ccn.hcam->notification_type ==
-           NOTIFICATION_TYPE_ENTRY_DELETED) {
+           NOTIFICATION_TYPE_ENTRY_DELETED || hidden_entry) {
                if (res->scsi_dev) {
+                       res->cfg_entry.unique_flags1 &= 0x7F;
                        res->change_detected = RES_CHANGE_DEL;
                        res->cfg_entry.resource_handle =
                                PMCRAID_INVALID_RES_HANDLE;
index 2752b56..92f89d5 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * pmcraid.h -- PMC Sierra MaxRAID controller driver header file
  *
+ * Written By: Anil Ravindranath<anil_ravindranath@pmc-sierra.com>
+ *             PMC-Sierra Inc
+ *
  * Copyright (C) 2008, 2009 PMC Sierra Inc.
  *
  * This program is free software; you can redistribute it and/or modify
 #define PMCRAID_VSET_LUN_ID                      0x0
 #define PMCRAID_PHYS_BUS_ID                      0x0
 #define PMCRAID_VIRTUAL_ENCL_BUS_ID              0x8
-#define PMCRAID_MAX_VSET_TARGETS                 240
+#define PMCRAID_MAX_VSET_TARGETS                 0x7F
 #define PMCRAID_MAX_VSET_LUNS_PER_TARGET         8
 
 #define PMCRAID_IOA_MAX_SECTORS                  32767
index 6b9bf23..384afda 100644 (file)
@@ -1570,9 +1570,6 @@ typedef struct fc_port {
        struct fc_rport *rport, *drport;
        u32 supported_classes;
 
-       unsigned long last_queue_full;
-       unsigned long last_ramp_up;
-
        uint16_t vp_idx;
 } fc_port_t;
 
@@ -2265,6 +2262,7 @@ struct qla_hw_data {
                uint32_t        port0                   :1;
                uint32_t        running_gold_fw         :1;
                uint32_t        cpu_affinity_enabled    :1;
+               uint32_t        disable_msix_handshake  :1;
        } flags;
 
        /* This spinlock is used to protect "io transactions", you must
@@ -2387,6 +2385,7 @@ struct qla_hw_data {
 #define IS_QLA81XX(ha)         (IS_QLA8001(ha))
 #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
                                IS_QLA25XX(ha) || IS_QLA81XX(ha))
+#define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha))
 #define IS_NOPOLLING_TYPE(ha)  ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
                                (ha)->flags.msix_enabled)
 #define IS_FAC_REQUIRED(ha)    (IS_QLA81XX(ha))
index e218513..0b6801f 100644 (file)
@@ -72,8 +72,6 @@ extern int ql2xloginretrycount;
 extern int ql2xfdmienable;
 extern int ql2xallocfwdump;
 extern int ql2xextended_error_logging;
-extern int ql2xqfullrampup;
-extern int ql2xqfulltracking;
 extern int ql2xiidmaenable;
 extern int ql2xmaxqueues;
 extern int ql2xmultique_tag;
index b74924b..73a7935 100644 (file)
@@ -1442,7 +1442,17 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                        icb->firmware_options_2 |=
                                __constant_cpu_to_le32(BIT_18);
 
-               icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22);
+               /* Use Disable MSIX Handshake mode for capable adapters */
+               if (IS_MSIX_NACK_CAPABLE(ha)) {
+                       icb->firmware_options_2 &=
+                               __constant_cpu_to_le32(~BIT_22);
+                       ha->flags.disable_msix_handshake = 1;
+                       qla_printk(KERN_INFO, ha,
+                               "MSIX Handshake Disable Mode turned on\n");
+               } else {
+                       icb->firmware_options_2 |=
+                               __constant_cpu_to_le32(BIT_22);
+               }
                icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23);
 
                WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
index 8049873..1692a88 100644 (file)
@@ -811,78 +811,6 @@ skip_rio:
                qla2x00_alert_all_vps(rsp, mb);
 }
 
-static void
-qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
-{
-       fc_port_t *fcport = data;
-       struct scsi_qla_host *vha = fcport->vha;
-       struct qla_hw_data *ha = vha->hw;
-       struct req_que *req = NULL;
-
-       if (!ql2xqfulltracking)
-               return;
-
-       req = vha->req;
-       if (!req)
-               return;
-       if (req->max_q_depth <= sdev->queue_depth)
-               return;
-
-       if (sdev->ordered_tags)
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
-                   sdev->queue_depth + 1);
-       else
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
-                   sdev->queue_depth + 1);
-
-       fcport->last_ramp_up = jiffies;
-
-       DEBUG2(qla_printk(KERN_INFO, ha,
-           "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
-           fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-           sdev->queue_depth));
-}
-
-static void
-qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data)
-{
-       fc_port_t *fcport = data;
-
-       if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1))
-               return;
-
-       DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
-           "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
-           fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-           sdev->queue_depth));
-}
-
-static inline void
-qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req,
-                                                               srb_t *sp)
-{
-       fc_port_t *fcport;
-       struct scsi_device *sdev;
-
-       if (!ql2xqfulltracking)
-               return;
-
-       sdev = sp->cmd->device;
-       if (sdev->queue_depth >= req->max_q_depth)
-               return;
-
-       fcport = sp->fcport;
-       if (time_before(jiffies,
-           fcport->last_ramp_up + ql2xqfullrampup * HZ))
-               return;
-       if (time_before(jiffies,
-           fcport->last_queue_full + ql2xqfullrampup * HZ))
-               return;
-
-       starget_for_each_device(sdev->sdev_target, fcport,
-           qla2x00_adjust_sdev_qdepth_up);
-}
-
 /**
  * qla2x00_process_completed_request() - Process a Fast Post response.
  * @ha: SCSI driver HA context
@@ -913,8 +841,6 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
 
                /* Save ISP completion status */
                sp->cmd->result = DID_OK << 16;
-
-               qla2x00_ramp_up_queue_depth(vha, req, sp);
                qla2x00_sp_compl(ha, sp);
        } else {
                DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion"
@@ -1435,13 +1361,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                            "scsi(%ld): QUEUE FULL status detected "
                            "0x%x-0x%x.\n", vha->host_no, comp_status,
                            scsi_status));
-
-                       /* Adjust queue depth for all luns on the port. */
-                       if (!ql2xqfulltracking)
-                               break;
-                       fcport->last_queue_full = jiffies;
-                       starget_for_each_device(cp->device->sdev_target,
-                           fcport, qla2x00_adjust_sdev_qdepth_down);
                        break;
                }
                if (lscsi_status != SS_CHECK_CONDITION)
@@ -1516,17 +1435,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
                                    "scsi(%ld): QUEUE FULL status detected "
                                    "0x%x-0x%x.\n", vha->host_no, comp_status,
                                    scsi_status));
-
-                               /*
-                                * Adjust queue depth for all luns on the
-                                * port.
-                                */
-                               if (!ql2xqfulltracking)
-                                       break;
-                               fcport->last_queue_full = jiffies;
-                               starget_for_each_device(
-                                   cp->device->sdev_target, fcport,
-                                   qla2x00_adjust_sdev_qdepth_down);
                                break;
                        }
                        if (lscsi_status != SS_CHECK_CONDITION)
@@ -2020,7 +1928,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
 
        vha = qla25xx_get_host(rsp);
        qla24xx_process_response_queue(vha, rsp);
-       if (!ha->mqenable) {
+       if (!ha->flags.disable_msix_handshake) {
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
                RD_REG_DWORD_RELAXED(&reg->hccr);
        }
@@ -2034,6 +1942,7 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
 {
        struct qla_hw_data *ha;
        struct rsp_que *rsp;
+       struct device_reg_24xx __iomem *reg;
 
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
@@ -2043,6 +1952,14 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
        }
        ha = rsp->hw;
 
+       /* Clear the interrupt, if enabled, for this response queue */
+       if (rsp->options & ~BIT_6) {
+               reg = &ha->iobase->isp24;
+               spin_lock_irq(&ha->hardware_lock);
+               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+               RD_REG_DWORD_RELAXED(&reg->hccr);
+               spin_unlock_irq(&ha->hardware_lock);
+       }
        queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work);
 
        return IRQ_HANDLED;
index a47d343..2a4c7f4 100644 (file)
@@ -696,6 +696,10 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        /* Use alternate PCI devfn */
        if (LSB(rsp->rid))
                options |= BIT_5;
+       /* Enable MSIX handshake mode on for uncapable adapters */
+       if (!IS_MSIX_NACK_CAPABLE(ha))
+               options |= BIT_6;
+
        rsp->options = options;
        rsp->id = que_id;
        reg = ISP_QUE_REG(ha, que_id);
index 4166935..2f873d2 100644 (file)
@@ -78,21 +78,6 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xmaxqdepth,
                "Maximum queue depth to report for target devices.");
 
-int ql2xqfulltracking = 1;
-module_param(ql2xqfulltracking, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xqfulltracking,
-               "Controls whether the driver tracks queue full status "
-               "returns and dynamically adjusts a scsi device's queue "
-               "depth.  Default is 1, perform tracking.  Set to 0 to "
-               "disable dynamic tracking and adjustment of queue depth.");
-
-int ql2xqfullrampup = 120;
-module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xqfullrampup,
-               "Number of seconds to wait to begin to ramp-up the queue "
-               "depth for a device after a queue-full condition has been "
-               "detected.  Default is 120 seconds.");
-
 int ql2xiidmaenable=1;
 module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xiidmaenable,
@@ -1217,13 +1202,61 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
        sdev->hostdata = NULL;
 }
 
+static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
+{
+       fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
+
+       if (!scsi_track_queue_full(sdev, qdepth))
+               return;
+
+       DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
+               "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
+               fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
+               sdev->queue_depth));
+}
+
+static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
+{
+       fc_port_t *fcport = sdev->hostdata;
+       struct scsi_qla_host *vha = fcport->vha;
+       struct qla_hw_data *ha = vha->hw;
+       struct req_que *req = NULL;
+
+       req = vha->req;
+       if (!req)
+               return;
+
+       if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
+               return;
+
+       if (sdev->ordered_tags)
+               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, qdepth);
+       else
+               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
+
+       DEBUG2(qla_printk(KERN_INFO, ha,
+              "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
+              fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
+              sdev->queue_depth));
+}
+
 static int
 qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
+       switch (reason) {
+       case SCSI_QDEPTH_DEFAULT:
+               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+               break;
+       case SCSI_QDEPTH_QFULL:
+               qla2x00_handle_queue_full(sdev, qdepth);
+               break;
+       case SCSI_QDEPTH_RAMP_UP:
+               qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
+               break;
+       default:
+               return EOPNOTSUPP;
+       }
 
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
        return sdev->queue_depth;
 }
 
@@ -2003,13 +2036,13 @@ skip_dpc:
        DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
            base_vha->host_no, ha));
 
-       base_vha->flags.init_done = 1;
-       base_vha->flags.online = 1;
-
        ret = scsi_add_host(host, &pdev->dev);
        if (ret)
                goto probe_failed;
 
+       base_vha->flags.init_done = 1;
+       base_vha->flags.online = 1;
+
        ha->isp_ops->enable_intrs(ha);
 
        scsi_scan_host(host);
index 807e0db..c482220 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.01-k7"
+#define QLA2XXX_VERSION      "8.03.01-k8"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
index e495d38..d892768 100644 (file)
@@ -859,6 +859,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                case 0x07: /* operation in progress */
                                case 0x08: /* Long write in progress */
                                case 0x09: /* self test in progress */
+                               case 0x14: /* space allocation in progress */
                                        action = ACTION_DELAYED_RETRY;
                                        break;
                                default:
index 6531c91..ddfcecd 100644 (file)
@@ -649,11 +649,22 @@ static __init int fc_transport_init(void)
                return error;
        error = transport_class_register(&fc_vport_class);
        if (error)
-               return error;
+               goto unreg_host_class;
        error = transport_class_register(&fc_rport_class);
        if (error)
-               return error;
-       return transport_class_register(&fc_transport_class);
+               goto unreg_vport_class;
+       error = transport_class_register(&fc_transport_class);
+       if (error)
+               goto unreg_rport_class;
+       return 0;
+
+unreg_rport_class:
+       transport_class_unregister(&fc_rport_class);
+unreg_vport_class:
+       transport_class_unregister(&fc_vport_class);
+unreg_host_class:
+       transport_class_unregister(&fc_host_class);
+       return error;
 }
 
 static void __exit fc_transport_exit(void)
index 9093c72..255da53 100644 (file)
@@ -264,6 +264,15 @@ sd_show_app_tag_own(struct device *dev, struct device_attribute *attr,
        return snprintf(buf, 20, "%u\n", sdkp->ATO);
 }
 
+static ssize_t
+sd_show_thin_provisioning(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->thin_provisioning);
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -274,6 +283,7 @@ static struct device_attribute sd_disk_attrs[] = {
               sd_store_manage_start_stop),
        __ATTR(protection_type, S_IRUGO, sd_show_protection_type, NULL),
        __ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
+       __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
        __ATTR_NULL,
 };
 
@@ -399,6 +409,57 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif)
 }
 
 /**
+ * sd_prepare_discard - unmap blocks on thinly provisioned device
+ * @rq: Request to prepare
+ *
+ * Will issue either UNMAP or WRITE SAME(16) depending on preference
+ * indicated by target device.
+ **/
+static int sd_prepare_discard(struct request *rq)
+{
+       struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+       struct bio *bio = rq->bio;
+       sector_t sector = bio->bi_sector;
+       unsigned int num = bio_sectors(bio);
+
+       if (sdkp->device->sector_size == 4096) {
+               sector >>= 3;
+               num >>= 3;
+       }
+
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
+       rq->timeout = SD_TIMEOUT;
+
+       memset(rq->cmd, 0, rq->cmd_len);
+
+       if (sdkp->unmap) {
+               char *buf = kmap_atomic(bio_page(bio), KM_USER0);
+
+               rq->cmd[0] = UNMAP;
+               rq->cmd[8] = 24;
+               rq->cmd_len = 10;
+
+               /* Ensure that data length matches payload */
+               rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24;
+
+               put_unaligned_be16(6 + 16, &buf[0]);
+               put_unaligned_be16(16, &buf[2]);
+               put_unaligned_be64(sector, &buf[8]);
+               put_unaligned_be32(num, &buf[16]);
+
+               kunmap_atomic(buf, KM_USER0);
+       } else {
+               rq->cmd[0] = WRITE_SAME_16;
+               rq->cmd[1] = 0x8; /* UNMAP */
+               put_unaligned_be64(sector, &rq->cmd[2]);
+               put_unaligned_be32(num, &rq->cmd[10]);
+               rq->cmd_len = 16;
+       }
+
+       return BLKPREP_OK;
+}
+
+/**
  *     sd_init_command - build a scsi (read or write) command from
  *     information in the request structure.
  *     @SCpnt: pointer to mid-level's per scsi command structure that
@@ -418,6 +479,13 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        int ret, host_dif;
        unsigned char protect;
 
+       /*
+        * Discard request come in as REQ_TYPE_FS but we turn them into
+        * block PC requests to make life easier.
+        */
+       if (blk_discard_rq(rq))
+               ret = sd_prepare_discard(rq);
+
        if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
                ret = scsi_setup_blk_pc_cmnd(sdp, rq);
                goto out;
@@ -1432,6 +1500,19 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
                sd_printk(KERN_NOTICE, sdkp,
                          "physical block alignment offset: %u\n", alignment);
 
+       if (buffer[14] & 0x80) { /* TPE */
+               struct request_queue *q = sdp->request_queue;
+
+               sdkp->thin_provisioning = 1;
+               q->limits.discard_granularity = sdkp->hw_sector_size;
+               q->limits.max_discard_sectors = 0xffffffff;
+
+               if (buffer[14] & 0x40) /* TPRZ */
+                       q->limits.discard_zeroes_data = 1;
+
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+       }
+
        sdkp->capacity = lba + 1;
        return sector_size;
 }
@@ -1863,6 +1944,7 @@ void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
+       struct request_queue *q = sdkp->disk->queue;
        unsigned int sector_sz = sdkp->device->sector_size;
        char *buffer;
 
@@ -1877,6 +1959,31 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        blk_queue_io_opt(sdkp->disk->queue,
                         get_unaligned_be32(&buffer[12]) * sector_sz);
 
+       /* Thin provisioning enabled and page length indicates TP support */
+       if (sdkp->thin_provisioning && buffer[3] == 0x3c) {
+               unsigned int lba_count, desc_count, granularity;
+
+               lba_count = get_unaligned_be32(&buffer[20]);
+               desc_count = get_unaligned_be32(&buffer[24]);
+
+               if (lba_count) {
+                       q->limits.max_discard_sectors =
+                               lba_count * sector_sz >> 9;
+
+                       if (desc_count)
+                               sdkp->unmap = 1;
+               }
+
+               granularity = get_unaligned_be32(&buffer[28]);
+
+               if (granularity)
+                       q->limits.discard_granularity = granularity * sector_sz;
+
+               if (buffer[32] & 0x80)
+                       q->limits.discard_alignment =
+                               get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+       }
+
        kfree(buffer);
 }
 
index e374804..43d3caf 100644 (file)
@@ -60,6 +60,8 @@ struct scsi_disk {
        unsigned        RCD : 1;        /* state of disk RCD bit, unused */
        unsigned        DPOFUA : 1;     /* state of disk DPOFUA bit */
        unsigned        first_scan : 1;
+       unsigned        thin_provisioning : 1;
+       unsigned        unmap : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
index ad59abb..d04ea9a 100644 (file)
@@ -552,13 +552,15 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
        SRpnt->waiting = waiting;
 
        if (STp->buffer->do_dio) {
+               mdata->page_order = 0;
                mdata->nr_entries = STp->buffer->sg_segs;
                mdata->pages = STp->buffer->mapped_pages;
        } else {
+               mdata->page_order = STp->buffer->reserved_page_order;
                mdata->nr_entries =
                        DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order);
-               STp->buffer->map_data.pages = STp->buffer->reserved_pages;
-               STp->buffer->map_data.offset = 0;
+               mdata->pages = STp->buffer->reserved_pages;
+               mdata->offset = 0;
        }
 
        memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
@@ -3719,7 +3721,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
                priority |= __GFP_ZERO;
 
        if (STbuffer->frp_segs) {
-               order = STbuffer->map_data.page_order;
+               order = STbuffer->reserved_page_order;
                b_size = PAGE_SIZE << order;
        } else {
                for (b_size = PAGE_SIZE, order = 0;
@@ -3752,7 +3754,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
                segs++;
        }
        STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
-       STbuffer->map_data.page_order = order;
+       STbuffer->reserved_page_order = order;
 
        return 1;
 }
@@ -3765,7 +3767,7 @@ static void clear_buffer(struct st_buffer * st_bp)
 
        for (i=0; i < st_bp->frp_segs; i++)
                memset(page_address(st_bp->reserved_pages[i]), 0,
-                      PAGE_SIZE << st_bp->map_data.page_order);
+                      PAGE_SIZE << st_bp->reserved_page_order);
        st_bp->cleared = 1;
 }
 
@@ -3773,7 +3775,7 @@ static void clear_buffer(struct st_buffer * st_bp)
 /* Release the extra buffer */
 static void normalize_buffer(struct st_buffer * STbuffer)
 {
-       int i, order = STbuffer->map_data.page_order;
+       int i, order = STbuffer->reserved_page_order;
 
        for (i = 0; i < STbuffer->frp_segs; i++) {
                __free_pages(STbuffer->reserved_pages[i], order);
@@ -3781,7 +3783,7 @@ static void normalize_buffer(struct st_buffer * STbuffer)
        }
        STbuffer->frp_segs = 0;
        STbuffer->sg_segs = 0;
-       STbuffer->map_data.page_order = 0;
+       STbuffer->reserved_page_order = 0;
        STbuffer->map_data.offset = 0;
 }
 
@@ -3791,7 +3793,7 @@ static void normalize_buffer(struct st_buffer * STbuffer)
 static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
 {
        int i, cnt, res, offset;
-       int length = PAGE_SIZE << st_bp->map_data.page_order;
+       int length = PAGE_SIZE << st_bp->reserved_page_order;
 
        for (i = 0, offset = st_bp->buffer_bytes;
             i < st_bp->frp_segs && offset >= length; i++)
@@ -3823,7 +3825,7 @@ static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, in
 static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
 {
        int i, cnt, res, offset;
-       int length = PAGE_SIZE << st_bp->map_data.page_order;
+       int length = PAGE_SIZE << st_bp->reserved_page_order;
 
        for (i = 0, offset = st_bp->read_pointer;
             i < st_bp->frp_segs && offset >= length; i++)
@@ -3856,7 +3858,7 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset)
 {
        int src_seg, dst_seg, src_offset = 0, dst_offset;
        int count, total;
-       int length = PAGE_SIZE << st_bp->map_data.page_order;
+       int length = PAGE_SIZE << st_bp->reserved_page_order;
 
        if (offset == 0)
                return;
@@ -4578,7 +4580,6 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
         }
 
        mdata->offset = uaddr & ~PAGE_MASK;
-       mdata->page_order = 0;
        STbp->mapped_pages = pages;
 
        return nr_pages;
index 544dc6b..f91a67c 100644 (file)
@@ -46,6 +46,7 @@ struct st_buffer {
        struct st_request *last_SRpnt;
        struct st_cmdstatus cmdstat;
        struct page **reserved_pages;
+       int reserved_page_order;
        struct page **mapped_pages;
        struct rq_map_data map_data;
        unsigned char *b_data;
index 2d9d703..f55eb01 100644 (file)
@@ -216,6 +216,17 @@ config SPI_S3C24XX
        help
          SPI driver for Samsung S3C24XX series ARM SoCs
 
+config SPI_S3C24XX_FIQ
+       bool "S3C24XX driver with FIQ pseudo-DMA"
+       depends on SPI_S3C24XX
+       select FIQ
+       help
+         Enable FIQ support for the S3C24XX SPI driver to provide pseudo
+         DMA by using the fast-interrupt request framework, This allows
+         the driver to get DMA-like performance when there are either
+         no free DMA channels, or when doing transfers that required both
+         TX and RX data paths.
+
 config SPI_S3C24XX_GPIO
        tristate "Samsung S3C24XX series SPI by GPIO"
        depends on ARCH_S3C2410 && EXPERIMENTAL
@@ -226,6 +237,13 @@ config SPI_S3C24XX_GPIO
          the inbuilt hardware cannot provide the transfer mode, or
          where the board is using non hardware connected pins.
 
+config SPI_S3C64XX
+       tristate "Samsung S3C64XX series type SPI"
+       depends on ARCH_S3C64XX && EXPERIMENTAL
+       select S3C64XX_DMA
+       help
+         SPI driver for Samsung S3C64XX and newer SoCs.
+
 config SPI_SH_MSIOF
        tristate "SuperH MSIOF SPI controller"
        depends on SUPERH && HAVE_CLK
@@ -289,6 +307,16 @@ config SPI_NUC900
 # Add new SPI master controllers in alphabetical order above this line
 #
 
+config SPI_DESIGNWARE
+       bool "DesignWare SPI controller core support"
+       depends on SPI_MASTER
+       help
+         general driver for SPI controller core from DesignWare
+
+config SPI_DW_PCI
+       tristate "PCI interface driver for DW SPI core"
+       depends on SPI_DESIGNWARE && PCI
+
 #
 # There are lots of SPI device types, with sensors and memory
 # being probably the most widely used ones.
index ed8c167..f3d2810 100644 (file)
@@ -16,6 +16,8 @@ obj-$(CONFIG_SPI_BFIN)                        += spi_bfin5xx.o
 obj-$(CONFIG_SPI_BITBANG)              += spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)               += au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi_butterfly.o
+obj-$(CONFIG_SPI_DESIGNWARE)           += dw_spi.o
+obj-$(CONFIG_SPI_DW_PCI)               += dw_spi_pci.o
 obj-$(CONFIG_SPI_GPIO)                 += spi_gpio.o
 obj-$(CONFIG_SPI_IMX)                  += spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)             += spi_lm70llp.o
@@ -30,7 +32,8 @@ obj-$(CONFIG_SPI_MPC52xx)             += mpc52xx_spi.o
 obj-$(CONFIG_SPI_MPC8xxx)              += spi_mpc8xxx.o
 obj-$(CONFIG_SPI_PPC4xx)               += spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
-obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx.o
+obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx_hw.o
+obj-$(CONFIG_SPI_S3C64XX)              += spi_s3c64xx.o
 obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
 obj-$(CONFIG_SPI_XILINX_OF)            += xilinx_spi_of.o
@@ -39,6 +42,11 @@ obj-$(CONFIG_SPI_SH_SCI)             += spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_MSIOF)             += spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)             += spi_stmp.o
 obj-$(CONFIG_SPI_NUC900)               += spi_nuc900.o
+
+# special build for s3c24xx spi driver with fiq support
+spi_s3c24xx_hw-y                       := spi_s3c24xx.o
+spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
+
 #      ... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
index f5b3fdb..d21c24e 100644 (file)
@@ -189,14 +189,14 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
 
        /* use scratch buffer only when rx or tx data is unspecified */
        if (xfer->rx_buf)
-               *rx_dma = xfer->rx_dma + xfer->len - len;
+               *rx_dma = xfer->rx_dma + xfer->len - *plen;
        else {
                *rx_dma = as->buffer_dma;
                if (len > BUFFER_SIZE)
                        len = BUFFER_SIZE;
        }
        if (xfer->tx_buf)
-               *tx_dma = xfer->tx_dma + xfer->len - len;
+               *tx_dma = xfer->tx_dma + xfer->len - *plen;
        else {
                *tx_dma = as->buffer_dma;
                if (len > BUFFER_SIZE)
@@ -788,7 +788,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
        spin_lock_init(&as->lock);
        INIT_LIST_HEAD(&as->queue);
        as->pdev = pdev;
-       as->regs = ioremap(regs->start, (regs->end - regs->start) + 1);
+       as->regs = ioremap(regs->start, resource_size(regs));
        if (!as->regs)
                goto out_free_buffer;
        as->irq = irq;
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
new file mode 100644 (file)
index 0000000..31620fa
--- /dev/null
@@ -0,0 +1,944 @@
+/*
+ * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+
+#include <linux/spi/dw_spi.h>
+#include <linux/spi/spi.h>
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+
+#define START_STATE    ((void *)0)
+#define RUNNING_STATE  ((void *)1)
+#define DONE_STATE     ((void *)2)
+#define ERROR_STATE    ((void *)-1)
+
+#define QUEUE_RUNNING  0
+#define QUEUE_STOPPED  1
+
+#define MRST_SPI_DEASSERT      0
+#define MRST_SPI_ASSERT                1
+
+/* Slave spi_dev related */
+struct chip_data {
+       u16 cr0;
+       u8 cs;                  /* chip select pin */
+       u8 n_bytes;             /* current is a 1/2/4 byte op */
+       u8 tmode;               /* TR/TO/RO/EEPROM */
+       u8 type;                /* SPI/SSP/MicroWire */
+
+       u8 poll_mode;           /* 1 means use poll mode */
+
+       u32 dma_width;
+       u32 rx_threshold;
+       u32 tx_threshold;
+       u8 enable_dma;
+       u8 bits_per_word;
+       u16 clk_div;            /* baud rate divider */
+       u32 speed_hz;           /* baud rate */
+       int (*write)(struct dw_spi *dws);
+       int (*read)(struct dw_spi *dws);
+       void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int spi_show_regs_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+#define SPI_REGS_BUFSIZE       1024
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct dw_spi *dws;
+       char *buf;
+       u32 len = 0;
+       ssize_t ret;
+
+       dws = file->private_data;
+
+       buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
+       if (!buf)
+               return 0;
+
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "MRST SPI0 registers:\n");
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "=================================\n");
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "SER: \t\t0x%08x\n", dw_readl(dws, ser));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "SR: \t\t0x%08x\n", dw_readl(dws, sr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "IMR: \t\t0x%08x\n", dw_readl(dws, imr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "ISR: \t\t0x%08x\n", dw_readl(dws, isr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
+       len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+                       "=================================\n");
+
+       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+       return ret;
+}
+
+static const struct file_operations mrst_spi_regs_ops = {
+       .owner          = THIS_MODULE,
+       .open           = spi_show_regs_open,
+       .read           = spi_show_regs,
+};
+
+static int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+       dws->debugfs = debugfs_create_dir("mrst_spi", NULL);
+       if (!dws->debugfs)
+               return -ENOMEM;
+
+       debugfs_create_file("registers", S_IFREG | S_IRUGO,
+               dws->debugfs, (void *)dws, &mrst_spi_regs_ops);
+       return 0;
+}
+
+static void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+       if (dws->debugfs)
+               debugfs_remove_recursive(dws->debugfs);
+}
+
+#else
+static inline int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+}
+
+static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static void wait_till_not_busy(struct dw_spi *dws)
+{
+       unsigned long end = jiffies + usecs_to_jiffies(1000);
+
+       while (time_before(jiffies, end)) {
+               if (!(dw_readw(dws, sr) & SR_BUSY))
+                       return;
+       }
+       dev_err(&dws->master->dev,
+               "DW SPI: Stutus keeps busy for 1000us after a read/write!\n");
+}
+
+static void flush(struct dw_spi *dws)
+{
+       while (dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+               dw_readw(dws, dr);
+
+       wait_till_not_busy(dws);
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static int null_writer(struct dw_spi *dws)
+{
+       u8 n_bytes = dws->n_bytes;
+
+       if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+               || (dws->tx == dws->tx_end))
+               return 0;
+       dw_writew(dws, dr, 0);
+       dws->tx += n_bytes;
+
+       wait_till_not_busy(dws);
+       return 1;
+}
+
+static int null_reader(struct dw_spi *dws)
+{
+       u8 n_bytes = dws->n_bytes;
+
+       while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+               && (dws->rx < dws->rx_end)) {
+               dw_readw(dws, dr);
+               dws->rx += n_bytes;
+       }
+       wait_till_not_busy(dws);
+       return dws->rx == dws->rx_end;
+}
+
+static int u8_writer(struct dw_spi *dws)
+{
+       if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+               || (dws->tx == dws->tx_end))
+               return 0;
+
+       dw_writew(dws, dr, *(u8 *)(dws->tx));
+       ++dws->tx;
+
+       wait_till_not_busy(dws);
+       return 1;
+}
+
+static int u8_reader(struct dw_spi *dws)
+{
+       while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+               && (dws->rx < dws->rx_end)) {
+               *(u8 *)(dws->rx) = dw_readw(dws, dr);
+               ++dws->rx;
+       }
+
+       wait_till_not_busy(dws);
+       return dws->rx == dws->rx_end;
+}
+
+static int u16_writer(struct dw_spi *dws)
+{
+       if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+               || (dws->tx == dws->tx_end))
+               return 0;
+
+       dw_writew(dws, dr, *(u16 *)(dws->tx));
+       dws->tx += 2;
+
+       wait_till_not_busy(dws);
+       return 1;
+}
+
+static int u16_reader(struct dw_spi *dws)
+{
+       u16 temp;
+
+       while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+               && (dws->rx < dws->rx_end)) {
+               temp = dw_readw(dws, dr);
+               *(u16 *)(dws->rx) = temp;
+               dws->rx += 2;
+       }
+
+       wait_till_not_busy(dws);
+       return dws->rx == dws->rx_end;
+}
+
+static void *next_transfer(struct dw_spi *dws)
+{
+       struct spi_message *msg = dws->cur_msg;
+       struct spi_transfer *trans = dws->cur_transfer;
+
+       /* Move to next transfer */
+       if (trans->transfer_list.next != &msg->transfers) {
+               dws->cur_transfer =
+                       list_entry(trans->transfer_list.next,
+                                       struct spi_transfer,
+                                       transfer_list);
+               return RUNNING_STATE;
+       } else
+               return DONE_STATE;
+}
+
+/*
+ * Note: first step is the protocol driver prepares
+ * a dma-capable memory, and this func just need translate
+ * the virt addr to physical
+ */
+static int map_dma_buffers(struct dw_spi *dws)
+{
+       if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
+               || !dws->cur_chip->enable_dma)
+               return 0;
+
+       if (dws->cur_transfer->tx_dma)
+               dws->tx_dma = dws->cur_transfer->tx_dma;
+
+       if (dws->cur_transfer->rx_dma)
+               dws->rx_dma = dws->cur_transfer->rx_dma;
+
+       return 1;
+}
+
+/* Caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct dw_spi *dws)
+{
+       struct spi_transfer *last_transfer;
+       unsigned long flags;
+       struct spi_message *msg;
+
+       spin_lock_irqsave(&dws->lock, flags);
+       msg = dws->cur_msg;
+       dws->cur_msg = NULL;
+       dws->cur_transfer = NULL;
+       dws->prev_chip = dws->cur_chip;
+       dws->cur_chip = NULL;
+       dws->dma_mapped = 0;
+       queue_work(dws->workqueue, &dws->pump_messages);
+       spin_unlock_irqrestore(&dws->lock, flags);
+
+       last_transfer = list_entry(msg->transfers.prev,
+                                       struct spi_transfer,
+                                       transfer_list);
+
+       if (!last_transfer->cs_change)
+               dws->cs_control(MRST_SPI_DEASSERT);
+
+       msg->state = NULL;
+       if (msg->complete)
+               msg->complete(msg->context);
+}
+
+static void int_error_stop(struct dw_spi *dws, const char *msg)
+{
+       /* Stop and reset hw */
+       flush(dws);
+       spi_enable_chip(dws, 0);
+
+       dev_err(&dws->master->dev, "%s\n", msg);
+       dws->cur_msg->state = ERROR_STATE;
+       tasklet_schedule(&dws->pump_transfers);
+}
+
+static void transfer_complete(struct dw_spi *dws)
+{
+       /* Update total byte transfered return count actual bytes read */
+       dws->cur_msg->actual_length += dws->len;
+
+       /* Move to next transfer */
+       dws->cur_msg->state = next_transfer(dws);
+
+       /* Handle end of message */
+       if (dws->cur_msg->state == DONE_STATE) {
+               dws->cur_msg->status = 0;
+               giveback(dws);
+       } else
+               tasklet_schedule(&dws->pump_transfers);
+}
+
+static irqreturn_t interrupt_transfer(struct dw_spi *dws)
+{
+       u16 irq_status, irq_mask = 0x3f;
+
+       irq_status = dw_readw(dws, isr) & irq_mask;
+       /* Error handling */
+       if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
+               dw_readw(dws, txoicr);
+               dw_readw(dws, rxoicr);
+               dw_readw(dws, rxuicr);
+               int_error_stop(dws, "interrupt_transfer: fifo overrun");
+               return IRQ_HANDLED;
+       }
+
+       /* INT comes from tx */
+       if (dws->tx && (irq_status & SPI_INT_TXEI)) {
+               while (dws->tx < dws->tx_end)
+                       dws->write(dws);
+
+               if (dws->tx == dws->tx_end) {
+                       spi_mask_intr(dws, SPI_INT_TXEI);
+                       transfer_complete(dws);
+               }
+       }
+
+       /* INT comes from rx */
+       if (dws->rx && (irq_status & SPI_INT_RXFI)) {
+               if (dws->read(dws))
+                       transfer_complete(dws);
+       }
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_spi_irq(int irq, void *dev_id)
+{
+       struct dw_spi *dws = dev_id;
+
+       if (!dws->cur_msg) {
+               spi_mask_intr(dws, SPI_INT_TXEI);
+               /* Never fail */
+               return IRQ_HANDLED;
+       }
+
+       return dws->transfer_handler(dws);
+}
+
+/* Must be called inside pump_transfers() */
+static void poll_transfer(struct dw_spi *dws)
+{
+       if (dws->tx) {
+               while (dws->write(dws))
+                       dws->read(dws);
+       }
+
+       dws->read(dws);
+       transfer_complete(dws);
+}
+
+static void dma_transfer(struct dw_spi *dws, int cs_change)
+{
+}
+
+static void pump_transfers(unsigned long data)
+{
+       struct dw_spi *dws = (struct dw_spi *)data;
+       struct spi_message *message = NULL;
+       struct spi_transfer *transfer = NULL;
+       struct spi_transfer *previous = NULL;
+       struct spi_device *spi = NULL;
+       struct chip_data *chip = NULL;
+       u8 bits = 0;
+       u8 imask = 0;
+       u8 cs_change = 0;
+       u16 clk_div = 0;
+       u32 speed = 0;
+       u32 cr0 = 0;
+
+       /* Get current state information */
+       message = dws->cur_msg;
+       transfer = dws->cur_transfer;
+       chip = dws->cur_chip;
+       spi = message->spi;
+
+       if (message->state == ERROR_STATE) {
+               message->status = -EIO;
+               goto early_exit;
+       }
+
+       /* Handle end of message */
+       if (message->state == DONE_STATE) {
+               message->status = 0;
+               goto early_exit;
+       }
+
+       /* Delay if requested at end of transfer*/
+       if (message->state == RUNNING_STATE) {
+               previous = list_entry(transfer->transfer_list.prev,
+                                       struct spi_transfer,
+                                       transfer_list);
+               if (previous->delay_usecs)
+                       udelay(previous->delay_usecs);
+       }
+
+       dws->n_bytes = chip->n_bytes;
+       dws->dma_width = chip->dma_width;
+       dws->cs_control = chip->cs_control;
+
+       dws->rx_dma = transfer->rx_dma;
+       dws->tx_dma = transfer->tx_dma;
+       dws->tx = (void *)transfer->tx_buf;
+       dws->tx_end = dws->tx + transfer->len;
+       dws->rx = transfer->rx_buf;
+       dws->rx_end = dws->rx + transfer->len;
+       dws->write = dws->tx ? chip->write : null_writer;
+       dws->read = dws->rx ? chip->read : null_reader;
+       dws->cs_change = transfer->cs_change;
+       dws->len = dws->cur_transfer->len;
+       if (chip != dws->prev_chip)
+               cs_change = 1;
+
+       cr0 = chip->cr0;
+
+       /* Handle per transfer options for bpw and speed */
+       if (transfer->speed_hz) {
+               speed = chip->speed_hz;
+
+               if (transfer->speed_hz != speed) {
+                       speed = transfer->speed_hz;
+                       if (speed > dws->max_freq) {
+                               printk(KERN_ERR "MRST SPI0: unsupported"
+                                       "freq: %dHz\n", speed);
+                               message->status = -EIO;
+                               goto early_exit;
+                       }
+
+                       /* clk_div doesn't support odd number */
+                       clk_div = dws->max_freq / speed;
+                       clk_div = (clk_div >> 1) << 1;
+
+                       chip->speed_hz = speed;
+                       chip->clk_div = clk_div;
+               }
+       }
+       if (transfer->bits_per_word) {
+               bits = transfer->bits_per_word;
+
+               switch (bits) {
+               case 8:
+                       dws->n_bytes = 1;
+                       dws->dma_width = 1;
+                       dws->read = (dws->read != null_reader) ?
+                                       u8_reader : null_reader;
+                       dws->write = (dws->write != null_writer) ?
+                                       u8_writer : null_writer;
+                       break;
+               case 16:
+                       dws->n_bytes = 2;
+                       dws->dma_width = 2;
+                       dws->read = (dws->read != null_reader) ?
+                                       u16_reader : null_reader;
+                       dws->write = (dws->write != null_writer) ?
+                                       u16_writer : null_writer;
+                       break;
+               default:
+                       printk(KERN_ERR "MRST SPI0: unsupported bits:"
+                               "%db\n", bits);
+                       message->status = -EIO;
+                       goto early_exit;
+               }
+
+               cr0 = (bits - 1)
+                       | (chip->type << SPI_FRF_OFFSET)
+                       | (spi->mode << SPI_MODE_OFFSET)
+                       | (chip->tmode << SPI_TMOD_OFFSET);
+       }
+       message->state = RUNNING_STATE;
+
+       /* Check if current transfer is a DMA transaction */
+       dws->dma_mapped = map_dma_buffers(dws);
+
+       if (!dws->dma_mapped && !chip->poll_mode) {
+               if (dws->rx)
+                       imask |= SPI_INT_RXFI;
+               if (dws->tx)
+                       imask |= SPI_INT_TXEI;
+               dws->transfer_handler = interrupt_transfer;
+       }
+
+       /*
+        * Reprogram registers only if
+        *      1. chip select changes
+        *      2. clk_div is changed
+        *      3. control value changes
+        */
+       if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div) {
+               spi_enable_chip(dws, 0);
+
+               if (dw_readw(dws, ctrl0) != cr0)
+                       dw_writew(dws, ctrl0, cr0);
+
+               /* Set the interrupt mask, for poll mode just diable all int */
+               spi_mask_intr(dws, 0xff);
+               if (!chip->poll_mode)
+                       spi_umask_intr(dws, imask);
+
+               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
+               spi_chip_sel(dws, spi->chip_select);
+               spi_enable_chip(dws, 1);
+
+               if (cs_change)
+                       dws->prev_chip = chip;
+       }
+
+       if (dws->dma_mapped)
+               dma_transfer(dws, cs_change);
+
+       if (chip->poll_mode)
+               poll_transfer(dws);
+
+       return;
+
+early_exit:
+       giveback(dws);
+       return;
+}
+
+static void pump_messages(struct work_struct *work)
+{
+       struct dw_spi *dws =
+               container_of(work, struct dw_spi, pump_messages);
+       unsigned long flags;
+
+       /* Lock queue and check for queue work */
+       spin_lock_irqsave(&dws->lock, flags);
+       if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
+               dws->busy = 0;
+               spin_unlock_irqrestore(&dws->lock, flags);
+               return;
+       }
+
+       /* Make sure we are not already running a message */
+       if (dws->cur_msg) {
+               spin_unlock_irqrestore(&dws->lock, flags);
+               return;
+       }
+
+       /* Extract head of queue */
+       dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
+       list_del_init(&dws->cur_msg->queue);
+
+       /* Initial message state*/
+       dws->cur_msg->state = START_STATE;
+       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
+                                               struct spi_transfer,
+                                               transfer_list);
+       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
+
+       /* Mark as busy and launch transfers */
+       tasklet_schedule(&dws->pump_transfers);
+
+       dws->busy = 1;
+       spin_unlock_irqrestore(&dws->lock, flags);
+}
+
+/* spi_device use this to queue in their spi_msg */
+static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+       struct dw_spi *dws = spi_master_get_devdata(spi->master);
+       unsigned long flags;
+
+       spin_lock_irqsave(&dws->lock, flags);
+
+       if (dws->run == QUEUE_STOPPED) {
+               spin_unlock_irqrestore(&dws->lock, flags);
+               return -ESHUTDOWN;
+       }
+
+       msg->actual_length = 0;
+       msg->status = -EINPROGRESS;
+       msg->state = START_STATE;
+
+       list_add_tail(&msg->queue, &dws->queue);
+
+       if (dws->run == QUEUE_RUNNING && !dws->busy) {
+
+               if (dws->cur_transfer || dws->cur_msg)
+                       queue_work(dws->workqueue,
+                                       &dws->pump_messages);
+               else {
+                       /* If no other data transaction in air, just go */
+                       spin_unlock_irqrestore(&dws->lock, flags);
+                       pump_messages(&dws->pump_messages);
+                       return 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&dws->lock, flags);
+       return 0;
+}
+
+/* This may be called twice for each spi dev */
+static int dw_spi_setup(struct spi_device *spi)
+{
+       struct dw_spi_chip *chip_info = NULL;
+       struct chip_data *chip;
+
+       if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
+               return -EINVAL;
+
+       /* Only alloc on first setup */
+       chip = spi_get_ctldata(spi);
+       if (!chip) {
+               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+               if (!chip)
+                       return -ENOMEM;
+
+               chip->cs_control = null_cs_control;
+               chip->enable_dma = 0;
+       }
+
+       /*
+        * Protocol drivers may change the chip settings, so...
+        * if chip_info exists, use it
+        */
+       chip_info = spi->controller_data;
+
+       /* chip_info doesn't always exist */
+       if (chip_info) {
+               if (chip_info->cs_control)
+                       chip->cs_control = chip_info->cs_control;
+
+               chip->poll_mode = chip_info->poll_mode;
+               chip->type = chip_info->type;
+
+               chip->rx_threshold = 0;
+               chip->tx_threshold = 0;
+
+               chip->enable_dma = chip_info->enable_dma;
+       }
+
+       if (spi->bits_per_word <= 8) {
+               chip->n_bytes = 1;
+               chip->dma_width = 1;
+               chip->read = u8_reader;
+               chip->write = u8_writer;
+       } else if (spi->bits_per_word <= 16) {
+               chip->n_bytes = 2;
+               chip->dma_width = 2;
+               chip->read = u16_reader;
+               chip->write = u16_writer;
+       } else {
+               /* Never take >16b case for MRST SPIC */
+               dev_err(&spi->dev, "invalid wordsize\n");
+               return -EINVAL;
+       }
+       chip->bits_per_word = spi->bits_per_word;
+
+       chip->speed_hz = spi->max_speed_hz;
+       if (chip->speed_hz)
+               chip->clk_div = 25000000 / chip->speed_hz;
+       else
+               chip->clk_div = 8;      /* default value */
+
+       chip->tmode = 0; /* Tx & Rx */
+       /* Default SPI mode is SCPOL = 0, SCPH = 0 */
+       chip->cr0 = (chip->bits_per_word - 1)
+                       | (chip->type << SPI_FRF_OFFSET)
+                       | (spi->mode  << SPI_MODE_OFFSET)
+                       | (chip->tmode << SPI_TMOD_OFFSET);
+
+       spi_set_ctldata(spi, chip);
+       return 0;
+}
+
+static void dw_spi_cleanup(struct spi_device *spi)
+{
+       struct chip_data *chip = spi_get_ctldata(spi);
+       kfree(chip);
+}
+
+static int __init init_queue(struct dw_spi *dws)
+{
+       INIT_LIST_HEAD(&dws->queue);
+       spin_lock_init(&dws->lock);
+
+       dws->run = QUEUE_STOPPED;
+       dws->busy = 0;
+
+       tasklet_init(&dws->pump_transfers,
+                       pump_transfers, (unsigned long)dws);
+
+       INIT_WORK(&dws->pump_messages, pump_messages);
+       dws->workqueue = create_singlethread_workqueue(
+                                       dev_name(dws->master->dev.parent));
+       if (dws->workqueue == NULL)
+               return -EBUSY;
+
+       return 0;
+}
+
+static int start_queue(struct dw_spi *dws)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dws->lock, flags);
+
+       if (dws->run == QUEUE_RUNNING || dws->busy) {
+               spin_unlock_irqrestore(&dws->lock, flags);
+               return -EBUSY;
+       }
+
+       dws->run = QUEUE_RUNNING;
+       dws->cur_msg = NULL;
+       dws->cur_transfer = NULL;
+       dws->cur_chip = NULL;
+       dws->prev_chip = NULL;
+       spin_unlock_irqrestore(&dws->lock, flags);
+
+       queue_work(dws->workqueue, &dws->pump_messages);
+
+       return 0;
+}
+
+static int stop_queue(struct dw_spi *dws)
+{
+       unsigned long flags;
+       unsigned limit = 50;
+       int status = 0;
+
+       spin_lock_irqsave(&dws->lock, flags);
+       dws->run = QUEUE_STOPPED;
+       while (!list_empty(&dws->queue) && dws->busy && limit--) {
+               spin_unlock_irqrestore(&dws->lock, flags);
+               msleep(10);
+               spin_lock_irqsave(&dws->lock, flags);
+       }
+
+       if (!list_empty(&dws->queue) || dws->busy)
+               status = -EBUSY;
+       spin_unlock_irqrestore(&dws->lock, flags);
+
+       return status;
+}
+
+static int destroy_queue(struct dw_spi *dws)
+{
+       int status;
+
+       status = stop_queue(dws);
+       if (status != 0)
+               return status;
+       destroy_workqueue(dws->workqueue);
+       return 0;
+}
+
+/* Restart the controller, disable all interrupts, clean rx fifo */
+static void spi_hw_init(struct dw_spi *dws)
+{
+       spi_enable_chip(dws, 0);
+       spi_mask_intr(dws, 0xff);
+       spi_enable_chip(dws, 1);
+       flush(dws);
+}
+
+int __devinit dw_spi_add_host(struct dw_spi *dws)
+{
+       struct spi_master *master;
+       int ret;
+
+       BUG_ON(dws == NULL);
+
+       master = spi_alloc_master(dws->parent_dev, 0);
+       if (!master) {
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       dws->master = master;
+       dws->type = SSI_MOTO_SPI;
+       dws->prev_chip = NULL;
+       dws->dma_inited = 0;
+       dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+
+       ret = request_irq(dws->irq, dw_spi_irq, 0,
+                       "dw_spi", dws);
+       if (ret < 0) {
+               dev_err(&master->dev, "can not get IRQ\n");
+               goto err_free_master;
+       }
+
+       master->mode_bits = SPI_CPOL | SPI_CPHA;
+       master->bus_num = dws->bus_num;
+       master->num_chipselect = dws->num_cs;
+       master->cleanup = dw_spi_cleanup;
+       master->setup = dw_spi_setup;
+       master->transfer = dw_spi_transfer;
+
+       dws->dma_inited = 0;
+
+       /* Basic HW init */
+       spi_hw_init(dws);
+
+       /* Initial and start queue */
+       ret = init_queue(dws);
+       if (ret) {
+               dev_err(&master->dev, "problem initializing queue\n");
+               goto err_diable_hw;
+       }
+       ret = start_queue(dws);
+       if (ret) {
+               dev_err(&master->dev, "problem starting queue\n");
+               goto err_diable_hw;
+       }
+
+       spi_master_set_devdata(master, dws);
+       ret = spi_register_master(master);
+       if (ret) {
+               dev_err(&master->dev, "problem registering spi master\n");
+               goto err_queue_alloc;
+       }
+
+       mrst_spi_debugfs_init(dws);
+       return 0;
+
+err_queue_alloc:
+       destroy_queue(dws);
+err_diable_hw:
+       spi_enable_chip(dws, 0);
+       free_irq(dws->irq, dws);
+err_free_master:
+       spi_master_put(master);
+exit:
+       return ret;
+}
+EXPORT_SYMBOL(dw_spi_add_host);
+
+void __devexit dw_spi_remove_host(struct dw_spi *dws)
+{
+       int status = 0;
+
+       if (!dws)
+               return;
+       mrst_spi_debugfs_remove(dws);
+
+       /* Remove the queue */
+       status = destroy_queue(dws);
+       if (status != 0)
+               dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
+                       "complete, message memory not freed\n");
+
+       spi_enable_chip(dws, 0);
+       /* Disable clk */
+       spi_set_clk(dws, 0);
+       free_irq(dws->irq, dws);
+
+       /* Disconnect from the SPI framework */
+       spi_unregister_master(dws->master);
+}
+
+int dw_spi_suspend_host(struct dw_spi *dws)
+{
+       int ret = 0;
+
+       ret = stop_queue(dws);
+       if (ret)
+               return ret;
+       spi_enable_chip(dws, 0);
+       spi_set_clk(dws, 0);
+       return ret;
+}
+EXPORT_SYMBOL(dw_spi_suspend_host);
+
+int dw_spi_resume_host(struct dw_spi *dws)
+{
+       int ret;
+
+       spi_hw_init(dws);
+       ret = start_queue(dws);
+       if (ret)
+               dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
+       return ret;
+}
+EXPORT_SYMBOL(dw_spi_resume_host);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
new file mode 100644 (file)
index 0000000..34ba691
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * mrst_spi_pci.c - PCI interface driver for DW SPI Core
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/spi/dw_spi.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "dw_spi_pci"
+
+struct dw_spi_pci {
+       struct pci_dev          *pdev;
+       struct dw_spi           dws;
+};
+
+static int __devinit spi_pci_probe(struct pci_dev *pdev,
+       const struct pci_device_id *ent)
+{
+       struct dw_spi_pci *dwpci;
+       struct dw_spi *dws;
+       int pci_bar = 0;
+       int ret;
+
+       printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
+               pdev->vendor, pdev->device);
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
+       if (!dwpci) {
+               ret = -ENOMEM;
+               goto err_disable;
+       }
+
+       dwpci->pdev = pdev;
+       dws = &dwpci->dws;
+
+       /* Get basic io resource and map it */
+       dws->paddr = pci_resource_start(pdev, pci_bar);
+       dws->iolen = pci_resource_len(pdev, pci_bar);
+
+       ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+       if (ret)
+               goto err_kfree;
+
+       dws->regs = ioremap_nocache((unsigned long)dws->paddr,
+                               pci_resource_len(pdev, pci_bar));
+       if (!dws->regs) {
+               ret = -ENOMEM;
+               goto err_release_reg;
+       }
+
+       dws->parent_dev = &pdev->dev;
+       dws->bus_num = 0;
+       dws->num_cs = 4;
+       dws->max_freq = 25000000;       /* for Moorestwon */
+       dws->irq = pdev->irq;
+
+       ret = dw_spi_add_host(dws);
+       if (ret)
+               goto err_unmap;
+
+       /* PCI hook and SPI hook use the same drv data */
+       pci_set_drvdata(pdev, dwpci);
+       return 0;
+
+err_unmap:
+       iounmap(dws->regs);
+err_release_reg:
+       pci_release_region(pdev, pci_bar);
+err_kfree:
+       kfree(dwpci);
+err_disable:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void __devexit spi_pci_remove(struct pci_dev *pdev)
+{
+       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+       iounmap(dwpci->dws.regs);
+       pci_release_region(pdev, 0);
+       kfree(dwpci);
+       pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+       int ret;
+
+       ret = dw_spi_suspend_host(&dwpci->dws);
+       if (ret)
+               return ret;
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return ret;
+}
+
+static int spi_resume(struct pci_dev *pdev)
+{
+       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+       return dw_spi_resume_host(&dwpci->dws);
+}
+#else
+#define spi_suspend    NULL
+#define spi_resume     NULL
+#endif
+
+static const struct pci_device_id pci_ids[] __devinitdata = {
+       /* Intel Moorestown platform SPI controller 0 */
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
+       {},
+};
+
+static struct pci_driver dw_spi_driver = {
+       .name =         DRIVER_NAME,
+       .id_table =     pci_ids,
+       .probe =        spi_pci_probe,
+       .remove =       __devexit_p(spi_pci_remove),
+       .suspend =      spi_suspend,
+       .resume =       spi_resume,
+};
+
+static int __init mrst_spi_init(void)
+{
+       return pci_register_driver(&dw_spi_driver);
+}
+
+static void __exit mrst_spi_exit(void)
+{
+       pci_unregister_driver(&dw_spi_driver);
+}
+
+module_init(mrst_spi_init);
+module_exit(mrst_spi_exit);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
+MODULE_LICENSE("GPL v2");
index 73e24ef..1d41058 100644 (file)
@@ -1294,7 +1294,7 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
                goto out_error_get_res;
        }
 
-       drv_data->regs_base = ioremap(res->start, (res->end - res->start + 1));
+       drv_data->regs_base = ioremap(res->start, resource_size(res));
        if (drv_data->regs_base == NULL) {
                dev_err(dev, "Cannot map IO\n");
                status = -ENXIO;
index e9390d7..1fb2a6e 100644 (file)
@@ -1013,7 +1013,7 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
 
        init_completion(&mpc8xxx_spi->done);
 
-       mpc8xxx_spi->base = ioremap(mem->start, mem->end - mem->start + 1);
+       mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
        if (mpc8xxx_spi->base == NULL) {
                ret = -ENOMEM;
                goto err_ioremap;
index 2765915..c010733 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/drivers/spi/spi_s3c24xx.c
  *
  * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
+ * Copyright 2006-2009 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
 #include <plat/regs-spi.h>
 #include <mach/spi.h>
 
+#include <plat/fiq.h>
+#include <asm/fiq.h>
+
+#include "spi_s3c24xx_fiq.h"
+
 /**
  * s3c24xx_spi_devstate - per device data
  * @hz: Last frequency calculated for @sppre field.
@@ -42,6 +47,13 @@ struct s3c24xx_spi_devstate {
        u8              sppre;
 };
 
+enum spi_fiq_mode {
+       FIQ_MODE_NONE   = 0,
+       FIQ_MODE_TX     = 1,
+       FIQ_MODE_RX     = 2,
+       FIQ_MODE_TXRX   = 3,
+};
+
 struct s3c24xx_spi {
        /* bitbang has to be first */
        struct spi_bitbang       bitbang;
@@ -52,6 +64,11 @@ struct s3c24xx_spi {
        int                      len;
        int                      count;
 
+       struct fiq_handler       fiq_handler;
+       enum spi_fiq_mode        fiq_mode;
+       unsigned char            fiq_inuse;
+       unsigned char            fiq_claimed;
+
        void                    (*set_cs)(struct s3c2410_spi_info *spi,
                                          int cs, int pol);
 
@@ -67,6 +84,7 @@ struct s3c24xx_spi {
        struct s3c2410_spi_info *pdata;
 };
 
+
 #define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
 #define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
 
@@ -127,7 +145,7 @@ static int s3c24xx_spi_update_state(struct spi_device *spi,
        }
 
        if (spi->mode != cs->mode) {
-               u8 spcon = SPCON_DEFAULT;
+               u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
 
                if (spi->mode & SPI_CPHA)
                        spcon |= S3C2410_SPCON_CPHA_FMTB;
@@ -214,13 +232,196 @@ static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
        return hw->tx ? hw->tx[count] : 0;
 }
 
+#ifdef CONFIG_SPI_S3C24XX_FIQ
+/* Support for FIQ based pseudo-DMA to improve the transfer speed.
+ *
+ * This code uses the assembly helper in spi_s3c24xx_spi.S which is
+ * used by the FIQ core to move data between main memory and the peripheral
+ * block. Since this is code running on the processor, there is no problem
+ * with cache coherency of the buffers, so we can use any buffer we like.
+ */
+
+/**
+ * struct spi_fiq_code - FIQ code and header
+ * @length: The length of the code fragment, excluding this header.
+ * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
+ * @data: The code itself to install as a FIQ handler.
+ */
+struct spi_fiq_code {
+       u32     length;
+       u32     ack_offset;
+       u8      data[0];
+};
+
+extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
+
+/**
+ * ack_bit - turn IRQ into IRQ acknowledgement bit
+ * @irq: The interrupt number
+ *
+ * Returns the bit to write to the interrupt acknowledge register.
+ */
+static inline u32 ack_bit(unsigned int irq)
+{
+       return 1 << (irq - IRQ_EINT0);
+}
+
+/**
+ * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
+ * @hw: The hardware state.
+ *
+ * Claim the FIQ handler (only one can be active at any one time) and
+ * then setup the correct transfer code for this transfer.
+ *
+ * This call updates all the necessary state information if sucessful,
+ * so the caller does not need to do anything more than start the transfer
+ * as normal, since the IRQ will have been re-routed to the FIQ handler.
+*/
+void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
+{
+       struct pt_regs regs;
+       enum spi_fiq_mode mode;
+       struct spi_fiq_code *code;
+       int ret;
+
+       if (!hw->fiq_claimed) {
+               /* try and claim fiq if we haven't got it, and if not
+                * then return and simply use another transfer method */
+
+               ret = claim_fiq(&hw->fiq_handler);
+               if (ret)
+                       return;
+       }
+
+       if (hw->tx && !hw->rx)
+               mode = FIQ_MODE_TX;
+       else if (hw->rx && !hw->tx)
+               mode = FIQ_MODE_RX;
+       else
+               mode = FIQ_MODE_TXRX;
+
+       regs.uregs[fiq_rspi] = (long)hw->regs;
+       regs.uregs[fiq_rrx]  = (long)hw->rx;
+       regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
+       regs.uregs[fiq_rcount] = hw->len - 1;
+       regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
+
+       set_fiq_regs(&regs);
+
+       if (hw->fiq_mode != mode) {
+               u32 *ack_ptr;
+
+               hw->fiq_mode = mode;
+
+               switch (mode) {
+               case FIQ_MODE_TX:
+                       code = &s3c24xx_spi_fiq_tx;
+                       break;
+               case FIQ_MODE_RX:
+                       code = &s3c24xx_spi_fiq_rx;
+                       break;
+               case FIQ_MODE_TXRX:
+                       code = &s3c24xx_spi_fiq_txrx;
+                       break;
+               default:
+                       code = NULL;
+               }
+
+               BUG_ON(!code);
+
+               ack_ptr = (u32 *)&code->data[code->ack_offset];
+               *ack_ptr = ack_bit(hw->irq);
+
+               set_fiq_handler(&code->data, code->length);
+       }
+
+       s3c24xx_set_fiq(hw->irq, true);
+
+       hw->fiq_mode = mode;
+       hw->fiq_inuse = 1;
+}
+
+/**
+ * s3c24xx_spi_fiqop - FIQ core code callback
+ * @pw: Data registered with the handler
+ * @release: Whether this is a release or a return.
+ *
+ * Called by the FIQ code when another module wants to use the FIQ, so
+ * return whether we are currently using this or not and then update our
+ * internal state.
+ */
+static int s3c24xx_spi_fiqop(void *pw, int release)
+{
+       struct s3c24xx_spi *hw = pw;
+       int ret = 0;
+
+       if (release) {
+               if (hw->fiq_inuse)
+                       ret = -EBUSY;
+
+               /* note, we do not need to unroute the FIQ, as the FIQ
+                * vector code de-routes it to signal the end of transfer */
+
+               hw->fiq_mode = FIQ_MODE_NONE;
+               hw->fiq_claimed = 0;
+       } else {
+               hw->fiq_claimed = 1;
+       }
+
+       return ret;
+}
+
+/**
+ * s3c24xx_spi_initfiq - setup the information for the FIQ core
+ * @hw: The hardware state.
+ *
+ * Setup the fiq_handler block to pass to the FIQ core.
+ */
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
+{
+       hw->fiq_handler.dev_id = hw;
+       hw->fiq_handler.name = dev_name(hw->dev);
+       hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
+}
+
+/**
+ * s3c24xx_spi_usefiq - return if we should be using FIQ.
+ * @hw: The hardware state.
+ *
+ * Return true if the platform data specifies whether this channel is
+ * allowed to use the FIQ.
+ */
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
+{
+       return hw->pdata->use_fiq;
+}
+
+/**
+ * s3c24xx_spi_usingfiq - return if channel is using FIQ
+ * @spi: The hardware state.
+ *
+ * Return whether the channel is currently using the FIQ (separate from
+ * whether the FIQ is claimed).
+ */
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
+{
+       return spi->fiq_inuse;
+}
+#else
+
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
+static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }
+
+#endif /* CONFIG_SPI_S3C24XX_FIQ */
+
 static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 {
        struct s3c24xx_spi *hw = to_hw(spi);
 
-       dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
-               t->tx_buf, t->rx_buf, t->len);
-
        hw->tx = t->tx_buf;
        hw->rx = t->rx_buf;
        hw->len = t->len;
@@ -228,11 +429,14 @@ static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 
        init_completion(&hw->done);
 
+       hw->fiq_inuse = 0;
+       if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
+               s3c24xx_spi_tryfiq(hw);
+
        /* send the first byte */
        writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
 
        wait_for_completion(&hw->done);
-
        return hw->count;
 }
 
@@ -254,17 +458,27 @@ static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
                goto irq_done;
        }
 
-       hw->count++;
+       if (!s3c24xx_spi_usingfiq(hw)) {
+               hw->count++;
 
-       if (hw->rx)
-               hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
+               if (hw->rx)
+                       hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
 
-       count++;
+               count++;
+
+               if (count < hw->len)
+                       writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
+               else
+                       complete(&hw->done);
+       } else {
+               hw->count = hw->len;
+               hw->fiq_inuse = 0;
+
+               if (hw->rx)
+                       hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
 
-       if (count < hw->len)
-               writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
-       else
                complete(&hw->done);
+       }
 
  irq_done:
        return IRQ_HANDLED;
@@ -322,6 +536,10 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, hw);
        init_completion(&hw->done);
 
+       /* initialise fiq handler */
+
+       s3c24xx_spi_initfiq(hw);
+
        /* setup the master state. */
 
        /* the spi->mode bits understood by this driver: */
diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi_s3c24xx_fiq.S
new file mode 100644 (file)
index 0000000..3793cae
--- /dev/null
@@ -0,0 +1,116 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.S
+ *
+ * Copyright 2009 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#include <mach/map.h>
+#include <mach/regs-irq.h>
+#include <plat/regs-spi.h>
+
+#include "spi_s3c24xx_fiq.h"
+
+       .text
+
+       @ entry to these routines is as follows, with the register names
+       @ defined in fiq.h so that they can be shared with the C files which
+       @ setup the calling registers.
+       @
+       @ fiq_rirq      The base of the IRQ registers to find S3C2410_SRCPND
+       @ fiq_rtmp      Temporary register to hold tx/rx data
+       @ fiq_rspi      The base of the SPI register block
+       @ fiq_rtx       The tx buffer pointer
+       @ fiq_rrx       The rx buffer pointer
+       @ fiq_rcount    The number of bytes to move
+
+       @ each entry starts with a word entry of how long it is
+       @ and an offset to the irq acknowledgment word
+
+ENTRY(s3c24xx_spi_fiq_rx)
+s3c24xx_spi_fix_rx:
+       .word   fiq_rx_end - fiq_rx_start
+       .word   fiq_rx_irq_ack - fiq_rx_start
+fiq_rx_start:
+       ldr     fiq_rtmp, fiq_rx_irq_ack
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+       ldrb    fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+       strb    fiq_rtmp, [ fiq_rrx ], #1
+
+       mov     fiq_rtmp, #0xff
+       strb    fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+       subs    fiq_rcount, fiq_rcount, #1
+       subnes  pc, lr, #4              @@ return, still have work to do
+
+       @@ set IRQ controller so that next op will trigger IRQ
+       mov     fiq_rtmp, #0
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+       subs    pc, lr, #4
+
+fiq_rx_irq_ack:
+       .word   0
+fiq_rx_end:
+
+ENTRY(s3c24xx_spi_fiq_txrx)
+s3c24xx_spi_fiq_txrx:
+       .word   fiq_txrx_end - fiq_txrx_start
+       .word   fiq_txrx_irq_ack - fiq_txrx_start
+fiq_txrx_start:
+
+       ldrb    fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+       strb    fiq_rtmp, [ fiq_rrx ], #1
+
+       ldr     fiq_rtmp, fiq_txrx_irq_ack
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+       ldrb    fiq_rtmp, [ fiq_rtx ], #1
+       strb    fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+       subs    fiq_rcount, fiq_rcount, #1
+       subnes  pc, lr, #4              @@ return, still have work to do
+
+       mov     fiq_rtmp, #0
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+       subs    pc, lr, #4
+
+fiq_txrx_irq_ack:
+       .word   0
+
+fiq_txrx_end:
+
+ENTRY(s3c24xx_spi_fiq_tx)
+s3c24xx_spi_fix_tx:
+       .word   fiq_tx_end - fiq_tx_start
+       .word   fiq_tx_irq_ack - fiq_tx_start
+fiq_tx_start:
+       ldrb    fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+
+       ldr     fiq_rtmp, fiq_tx_irq_ack
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+       ldrb    fiq_rtmp, [ fiq_rtx ], #1
+       strb    fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+       subs    fiq_rcount, fiq_rcount, #1
+       subnes  pc, lr, #4              @@ return, still have work to do
+
+       mov     fiq_rtmp, #0
+       str     fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+       subs    pc, lr, #4
+
+fiq_tx_irq_ack:
+       .word   0
+
+fiq_tx_end:
+
+       .end
diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi_s3c24xx_fiq.h
new file mode 100644 (file)
index 0000000..a5950bb
--- /dev/null
@@ -0,0 +1,26 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* We have R8 through R13 to play with */
+
+#ifdef __ASSEMBLY__
+#define __REG_NR(x)     r##x
+#else
+#define __REG_NR(x)     (x)
+#endif
+
+#define fiq_rspi       __REG_NR(8)
+#define fiq_rtmp       __REG_NR(9)
+#define fiq_rrx                __REG_NR(10)
+#define fiq_rtx                __REG_NR(11)
+#define fiq_rcount     __REG_NR(12)
+#define fiq_rirq       __REG_NR(13)
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
new file mode 100644 (file)
index 0000000..88a456d
--- /dev/null
@@ -0,0 +1,1196 @@
+/* linux/drivers/spi/spi_s3c64xx.c
+ *
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+#include <plat/spi.h>
+
+/* Registers and bit-fields */
+
+#define S3C64XX_SPI_CH_CFG             0x00
+#define S3C64XX_SPI_CLK_CFG            0x04
+#define S3C64XX_SPI_MODE_CFG   0x08
+#define S3C64XX_SPI_SLAVE_SEL  0x0C
+#define S3C64XX_SPI_INT_EN             0x10
+#define S3C64XX_SPI_STATUS             0x14
+#define S3C64XX_SPI_TX_DATA            0x18
+#define S3C64XX_SPI_RX_DATA            0x1C
+#define S3C64XX_SPI_PACKET_CNT 0x20
+#define S3C64XX_SPI_PENDING_CLR        0x24
+#define S3C64XX_SPI_SWAP_CFG   0x28
+#define S3C64XX_SPI_FB_CLK             0x2C
+
+#define S3C64XX_SPI_CH_HS_EN           (1<<6)  /* High Speed Enable */
+#define S3C64XX_SPI_CH_SW_RST          (1<<5)
+#define S3C64XX_SPI_CH_SLAVE           (1<<4)
+#define S3C64XX_SPI_CPOL_L             (1<<3)
+#define S3C64XX_SPI_CPHA_B             (1<<2)
+#define S3C64XX_SPI_CH_RXCH_ON         (1<<1)
+#define S3C64XX_SPI_CH_TXCH_ON         (1<<0)
+
+#define S3C64XX_SPI_CLKSEL_SRCMSK      (3<<9)
+#define S3C64XX_SPI_CLKSEL_SRCSHFT     9
+#define S3C64XX_SPI_ENCLK_ENABLE       (1<<8)
+#define S3C64XX_SPI_PSR_MASK           0xff
+
+#define S3C64XX_SPI_MODE_CH_TSZ_BYTE           (0<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD       (1<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_WORD           (2<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_MASK           (3<<29)
+#define S3C64XX_SPI_MODE_BUS_TSZ_BYTE          (0<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD      (1<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_WORD          (2<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_MASK          (3<<17)
+#define S3C64XX_SPI_MODE_RXDMA_ON              (1<<2)
+#define S3C64XX_SPI_MODE_TXDMA_ON              (1<<1)
+#define S3C64XX_SPI_MODE_4BURST                        (1<<0)
+
+#define S3C64XX_SPI_SLAVE_AUTO                 (1<<1)
+#define S3C64XX_SPI_SLAVE_SIG_INACT            (1<<0)
+
+#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
+                                       (c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_INT_TRAILING_EN            (1<<6)
+#define S3C64XX_SPI_INT_RX_OVERRUN_EN          (1<<5)
+#define S3C64XX_SPI_INT_RX_UNDERRUN_EN         (1<<4)
+#define S3C64XX_SPI_INT_TX_OVERRUN_EN          (1<<3)
+#define S3C64XX_SPI_INT_TX_UNDERRUN_EN         (1<<2)
+#define S3C64XX_SPI_INT_RX_FIFORDY_EN          (1<<1)
+#define S3C64XX_SPI_INT_TX_FIFORDY_EN          (1<<0)
+
+#define S3C64XX_SPI_ST_RX_OVERRUN_ERR          (1<<5)
+#define S3C64XX_SPI_ST_RX_UNDERRUN_ERR (1<<4)
+#define S3C64XX_SPI_ST_TX_OVERRUN_ERR          (1<<3)
+#define S3C64XX_SPI_ST_TX_UNDERRUN_ERR (1<<2)
+#define S3C64XX_SPI_ST_RX_FIFORDY              (1<<1)
+#define S3C64XX_SPI_ST_TX_FIFORDY              (1<<0)
+
+#define S3C64XX_SPI_PACKET_CNT_EN              (1<<16)
+
+#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR                (1<<4)
+#define S3C64XX_SPI_PND_TX_OVERRUN_CLR         (1<<3)
+#define S3C64XX_SPI_PND_RX_UNDERRUN_CLR                (1<<2)
+#define S3C64XX_SPI_PND_RX_OVERRUN_CLR         (1<<1)
+#define S3C64XX_SPI_PND_TRAILING_CLR           (1<<0)
+
+#define S3C64XX_SPI_SWAP_RX_HALF_WORD          (1<<7)
+#define S3C64XX_SPI_SWAP_RX_BYTE               (1<<6)
+#define S3C64XX_SPI_SWAP_RX_BIT                        (1<<5)
+#define S3C64XX_SPI_SWAP_RX_EN                 (1<<4)
+#define S3C64XX_SPI_SWAP_TX_HALF_WORD          (1<<3)
+#define S3C64XX_SPI_SWAP_TX_BYTE               (1<<2)
+#define S3C64XX_SPI_SWAP_TX_BIT                        (1<<1)
+#define S3C64XX_SPI_SWAP_TX_EN                 (1<<0)
+
+#define S3C64XX_SPI_FBCLK_MSK          (3<<0)
+
+#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
+                                       (((i)->fifo_lvl_mask + 1))) \
+                                       ? 1 : 0)
+
+#define S3C64XX_SPI_ST_TX_DONE(v, i) ((((v) >> (i)->rx_lvl_offset) & \
+                                       (((i)->fifo_lvl_mask + 1) << 1)) \
+                                       ? 1 : 0)
+#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
+#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
+
+#define S3C64XX_SPI_MAX_TRAILCNT       0x3ff
+#define S3C64XX_SPI_TRAILCNT_OFF       19
+
+#define S3C64XX_SPI_TRAILCNT           S3C64XX_SPI_MAX_TRAILCNT
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+#define SUSPND    (1<<0)
+#define SPIBUSY   (1<<1)
+#define RXBUSY    (1<<2)
+#define TXBUSY    (1<<3)
+
+/**
+ * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
+ * @clk: Pointer to the spi clock.
+ * @master: Pointer to the SPI Protocol master.
+ * @workqueue: Work queue for the SPI xfer requests.
+ * @cntrlr_info: Platform specific data for the controller this driver manages.
+ * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
+ * @work: Work
+ * @queue: To log SPI xfer requests.
+ * @lock: Controller specific lock.
+ * @state: Set of FLAGS to indicate status.
+ * @rx_dmach: Controller's DMA channel for Rx.
+ * @tx_dmach: Controller's DMA channel for Tx.
+ * @sfr_start: BUS address of SPI controller regs.
+ * @regs: Pointer to ioremap'ed controller registers.
+ * @xfer_completion: To indicate completion of xfer task.
+ * @cur_mode: Stores the active configuration of the controller.
+ * @cur_bpw: Stores the active bits per word settings.
+ * @cur_speed: Stores the active xfer clock speed.
+ */
+struct s3c64xx_spi_driver_data {
+       void __iomem                    *regs;
+       struct clk                      *clk;
+       struct platform_device          *pdev;
+       struct spi_master               *master;
+       struct workqueue_struct         *workqueue;
+       struct s3c64xx_spi_cntrlr_info  *cntrlr_info;
+       struct spi_device               *tgl_spi;
+       struct work_struct              work;
+       struct list_head                queue;
+       spinlock_t                      lock;
+       enum dma_ch                     rx_dmach;
+       enum dma_ch                     tx_dmach;
+       unsigned long                   sfr_start;
+       struct completion               xfer_completion;
+       unsigned                        state;
+       unsigned                        cur_mode, cur_bpw;
+       unsigned                        cur_speed;
+};
+
+static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
+       .name = "samsung-spi-dma",
+};
+
+static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       void __iomem *regs = sdd->regs;
+       unsigned long loops;
+       u32 val;
+
+       writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+       val = readl(regs + S3C64XX_SPI_CH_CFG);
+       val |= S3C64XX_SPI_CH_SW_RST;
+       val &= ~S3C64XX_SPI_CH_HS_EN;
+       writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+       /* Flush TxFIFO*/
+       loops = msecs_to_loops(1);
+       do {
+               val = readl(regs + S3C64XX_SPI_STATUS);
+       } while (TX_FIFO_LVL(val, sci) && loops--);
+
+       /* Flush RxFIFO*/
+       loops = msecs_to_loops(1);
+       do {
+               val = readl(regs + S3C64XX_SPI_STATUS);
+               if (RX_FIFO_LVL(val, sci))
+                       readl(regs + S3C64XX_SPI_RX_DATA);
+               else
+                       break;
+       } while (loops--);
+
+       val = readl(regs + S3C64XX_SPI_CH_CFG);
+       val &= ~S3C64XX_SPI_CH_SW_RST;
+       writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+       val = readl(regs + S3C64XX_SPI_MODE_CFG);
+       val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+       writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+       val = readl(regs + S3C64XX_SPI_CH_CFG);
+       val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
+       writel(val, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer, int dma_mode)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       void __iomem *regs = sdd->regs;
+       u32 modecfg, chcfg;
+
+       modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
+       modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+
+       chcfg = readl(regs + S3C64XX_SPI_CH_CFG);
+       chcfg &= ~S3C64XX_SPI_CH_TXCH_ON;
+
+       if (dma_mode) {
+               chcfg &= ~S3C64XX_SPI_CH_RXCH_ON;
+       } else {
+               /* Always shift in data in FIFO, even if xfer is Tx only,
+                * this helps setting PCKT_CNT value for generating clocks
+                * as exactly needed.
+                */
+               chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+               writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+                                       | S3C64XX_SPI_PACKET_CNT_EN,
+                                       regs + S3C64XX_SPI_PACKET_CNT);
+       }
+
+       if (xfer->tx_buf != NULL) {
+               sdd->state |= TXBUSY;
+               chcfg |= S3C64XX_SPI_CH_TXCH_ON;
+               if (dma_mode) {
+                       modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
+                       s3c2410_dma_config(sdd->tx_dmach, 1);
+                       s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
+                                               xfer->tx_dma, xfer->len);
+                       s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+               } else {
+                       unsigned char *buf = (unsigned char *) xfer->tx_buf;
+                       int i = 0;
+                       while (i < xfer->len)
+                               writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
+               }
+       }
+
+       if (xfer->rx_buf != NULL) {
+               sdd->state |= RXBUSY;
+
+               if (sci->high_speed && sdd->cur_speed >= 30000000UL
+                                       && !(sdd->cur_mode & SPI_CPHA))
+                       chcfg |= S3C64XX_SPI_CH_HS_EN;
+
+               if (dma_mode) {
+                       modecfg |= S3C64XX_SPI_MODE_RXDMA_ON;
+                       chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+                       writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+                                       | S3C64XX_SPI_PACKET_CNT_EN,
+                                       regs + S3C64XX_SPI_PACKET_CNT);
+                       s3c2410_dma_config(sdd->rx_dmach, 1);
+                       s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
+                                               xfer->rx_dma, xfer->len);
+                       s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+               }
+       }
+
+       writel(modecfg, regs + S3C64XX_SPI_MODE_CFG);
+       writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
+                                               struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs;
+
+       if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
+               if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
+                       /* Deselect the last toggled device */
+                       cs = sdd->tgl_spi->controller_data;
+                       cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1);
+               }
+               sdd->tgl_spi = NULL;
+       }
+
+       cs = spi->controller_data;
+       cs->set_level(spi->mode & SPI_CS_HIGH ? 1 : 0);
+}
+
+static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
+                               struct spi_transfer *xfer, int dma_mode)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       void __iomem *regs = sdd->regs;
+       unsigned long val;
+       int ms;
+
+       /* millisecs to xfer 'len' bytes @ 'cur_speed' */
+       ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+       ms += 5; /* some tolerance */
+
+       if (dma_mode) {
+               val = msecs_to_jiffies(ms) + 10;
+               val = wait_for_completion_timeout(&sdd->xfer_completion, val);
+       } else {
+               val = msecs_to_loops(ms);
+               do {
+                       val = readl(regs + S3C64XX_SPI_STATUS);
+               } while (RX_FIFO_LVL(val, sci) < xfer->len && --val);
+       }
+
+       if (!val)
+               return -EIO;
+
+       if (dma_mode) {
+               u32 status;
+
+               /*
+                * DmaTx returns after simply writing data in the FIFO,
+                * w/o waiting for real transmission on the bus to finish.
+                * DmaRx returns only after Dma read data from FIFO which
+                * needs bus transmission to finish, so we don't worry if
+                * Xfer involved Rx(with or without Tx).
+                */
+               if (xfer->rx_buf == NULL) {
+                       val = msecs_to_loops(10);
+                       status = readl(regs + S3C64XX_SPI_STATUS);
+                       while ((TX_FIFO_LVL(status, sci)
+                               || !S3C64XX_SPI_ST_TX_DONE(status, sci))
+                                       && --val) {
+                               cpu_relax();
+                               status = readl(regs + S3C64XX_SPI_STATUS);
+                       }
+
+                       if (!val)
+                               return -EIO;
+               }
+       } else {
+               unsigned char *buf;
+               int i;
+
+               /* If it was only Tx */
+               if (xfer->rx_buf == NULL) {
+                       sdd->state &= ~TXBUSY;
+                       return 0;
+               }
+
+               i = 0;
+               buf = xfer->rx_buf;
+               while (i < xfer->len)
+                       buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
+
+               sdd->state &= ~RXBUSY;
+       }
+
+       return 0;
+}
+
+static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
+                                               struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+
+       if (sdd->tgl_spi == spi)
+               sdd->tgl_spi = NULL;
+
+       cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1);
+}
+
+static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       void __iomem *regs = sdd->regs;
+       u32 val;
+
+       /* Disable Clock */
+       val = readl(regs + S3C64XX_SPI_CLK_CFG);
+       val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+       writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+       /* Set Polarity and Phase */
+       val = readl(regs + S3C64XX_SPI_CH_CFG);
+       val &= ~(S3C64XX_SPI_CH_SLAVE |
+                       S3C64XX_SPI_CPOL_L |
+                       S3C64XX_SPI_CPHA_B);
+
+       if (sdd->cur_mode & SPI_CPOL)
+               val |= S3C64XX_SPI_CPOL_L;
+
+       if (sdd->cur_mode & SPI_CPHA)
+               val |= S3C64XX_SPI_CPHA_B;
+
+       writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+       /* Set Channel & DMA Mode */
+       val = readl(regs + S3C64XX_SPI_MODE_CFG);
+       val &= ~(S3C64XX_SPI_MODE_BUS_TSZ_MASK
+                       | S3C64XX_SPI_MODE_CH_TSZ_MASK);
+
+       switch (sdd->cur_bpw) {
+       case 32:
+               val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
+               break;
+       case 16:
+               val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
+               break;
+       default:
+               val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
+               break;
+       }
+       val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
+
+       writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+       /* Configure Clock */
+       val = readl(regs + S3C64XX_SPI_CLK_CFG);
+       val &= ~S3C64XX_SPI_PSR_MASK;
+       val |= ((clk_get_rate(sci->src_clk) / sdd->cur_speed / 2 - 1)
+                       & S3C64XX_SPI_PSR_MASK);
+       writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+       /* Enable Clock */
+       val = readl(regs + S3C64XX_SPI_CLK_CFG);
+       val |= S3C64XX_SPI_ENCLK_ENABLE;
+       writel(val, regs + S3C64XX_SPI_CLK_CFG);
+}
+
+void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
+                               int size, enum s3c2410_dma_buffresult res)
+{
+       struct s3c64xx_spi_driver_data *sdd = buf_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       if (res == S3C2410_RES_OK)
+               sdd->state &= ~RXBUSY;
+       else
+               dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
+
+       /* If the other done */
+       if (!(sdd->state & TXBUSY))
+               complete(&sdd->xfer_completion);
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
+                               int size, enum s3c2410_dma_buffresult res)
+{
+       struct s3c64xx_spi_driver_data *sdd = buf_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       if (res == S3C2410_RES_OK)
+               sdd->state &= ~TXBUSY;
+       else
+               dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
+
+       /* If the other done */
+       if (!(sdd->state & RXBUSY))
+               complete(&sdd->xfer_completion);
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
+
+static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
+                                               struct spi_message *msg)
+{
+       struct device *dev = &sdd->pdev->dev;
+       struct spi_transfer *xfer;
+
+       if (msg->is_dma_mapped)
+               return 0;
+
+       /* First mark all xfer unmapped */
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               xfer->rx_dma = XFER_DMAADDR_INVALID;
+               xfer->tx_dma = XFER_DMAADDR_INVALID;
+       }
+
+       /* Map until end or first fail */
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+               if (xfer->tx_buf != NULL) {
+                       xfer->tx_dma = dma_map_single(dev, xfer->tx_buf,
+                                               xfer->len, DMA_TO_DEVICE);
+                       if (dma_mapping_error(dev, xfer->tx_dma)) {
+                               dev_err(dev, "dma_map_single Tx failed\n");
+                               xfer->tx_dma = XFER_DMAADDR_INVALID;
+                               return -ENOMEM;
+                       }
+               }
+
+               if (xfer->rx_buf != NULL) {
+                       xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
+                                               xfer->len, DMA_FROM_DEVICE);
+                       if (dma_mapping_error(dev, xfer->rx_dma)) {
+                               dev_err(dev, "dma_map_single Rx failed\n");
+                               dma_unmap_single(dev, xfer->tx_dma,
+                                               xfer->len, DMA_TO_DEVICE);
+                               xfer->tx_dma = XFER_DMAADDR_INVALID;
+                               xfer->rx_dma = XFER_DMAADDR_INVALID;
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
+                                               struct spi_message *msg)
+{
+       struct device *dev = &sdd->pdev->dev;
+       struct spi_transfer *xfer;
+
+       if (msg->is_dma_mapped)
+               return;
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+               if (xfer->rx_buf != NULL
+                               && xfer->rx_dma != XFER_DMAADDR_INVALID)
+                       dma_unmap_single(dev, xfer->rx_dma,
+                                               xfer->len, DMA_FROM_DEVICE);
+
+               if (xfer->tx_buf != NULL
+                               && xfer->tx_dma != XFER_DMAADDR_INVALID)
+                       dma_unmap_single(dev, xfer->tx_dma,
+                                               xfer->len, DMA_TO_DEVICE);
+       }
+}
+
+static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
+                                       struct spi_message *msg)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       struct spi_device *spi = msg->spi;
+       struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+       struct spi_transfer *xfer;
+       int status = 0, cs_toggle = 0;
+       u32 speed;
+       u8 bpw;
+
+       /* If Master's(controller) state differs from that needed by Slave */
+       if (sdd->cur_speed != spi->max_speed_hz
+                       || sdd->cur_mode != spi->mode
+                       || sdd->cur_bpw != spi->bits_per_word) {
+               sdd->cur_bpw = spi->bits_per_word;
+               sdd->cur_speed = spi->max_speed_hz;
+               sdd->cur_mode = spi->mode;
+               s3c64xx_spi_config(sdd);
+       }
+
+       /* Map all the transfers if needed */
+       if (s3c64xx_spi_map_mssg(sdd, msg)) {
+               dev_err(&spi->dev,
+                       "Xfer: Unable to map message buffers!\n");
+               status = -ENOMEM;
+               goto out;
+       }
+
+       /* Configure feedback delay */
+       writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+               unsigned long flags;
+               int use_dma;
+
+               INIT_COMPLETION(sdd->xfer_completion);
+
+               /* Only BPW and Speed may change across transfers */
+               bpw = xfer->bits_per_word ? : spi->bits_per_word;
+               speed = xfer->speed_hz ? : spi->max_speed_hz;
+
+               if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
+                       sdd->cur_bpw = bpw;
+                       sdd->cur_speed = speed;
+                       s3c64xx_spi_config(sdd);
+               }
+
+               /* Polling method for xfers not bigger than FIFO capacity */
+               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+                       use_dma = 0;
+               else
+                       use_dma = 1;
+
+               spin_lock_irqsave(&sdd->lock, flags);
+
+               /* Pending only which is to be done */
+               sdd->state &= ~RXBUSY;
+               sdd->state &= ~TXBUSY;
+
+               enable_datapath(sdd, spi, xfer, use_dma);
+
+               /* Slave Select */
+               enable_cs(sdd, spi);
+
+               /* Start the signals */
+               S3C64XX_SPI_ACT(sdd);
+
+               spin_unlock_irqrestore(&sdd->lock, flags);
+
+               status = wait_for_xfer(sdd, xfer, use_dma);
+
+               /* Quiese the signals */
+               S3C64XX_SPI_DEACT(sdd);
+
+               if (status) {
+                       dev_err(&spi->dev, "I/O Error: \
+                               rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
+                               xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
+                               (sdd->state & RXBUSY) ? 'f' : 'p',
+                               (sdd->state & TXBUSY) ? 'f' : 'p',
+                               xfer->len);
+
+                       if (use_dma) {
+                               if (xfer->tx_buf != NULL
+                                               && (sdd->state & TXBUSY))
+                                       s3c2410_dma_ctrl(sdd->tx_dmach,
+                                                       S3C2410_DMAOP_FLUSH);
+                               if (xfer->rx_buf != NULL
+                                               && (sdd->state & RXBUSY))
+                                       s3c2410_dma_ctrl(sdd->rx_dmach,
+                                                       S3C2410_DMAOP_FLUSH);
+                       }
+
+                       goto out;
+               }
+
+               if (xfer->delay_usecs)
+                       udelay(xfer->delay_usecs);
+
+               if (xfer->cs_change) {
+                       /* Hint that the next mssg is gonna be
+                          for the same device */
+                       if (list_is_last(&xfer->transfer_list,
+                                               &msg->transfers))
+                               cs_toggle = 1;
+                       else
+                               disable_cs(sdd, spi);
+               }
+
+               msg->actual_length += xfer->len;
+
+               flush_fifo(sdd);
+       }
+
+out:
+       if (!cs_toggle || status)
+               disable_cs(sdd, spi);
+       else
+               sdd->tgl_spi = spi;
+
+       s3c64xx_spi_unmap_mssg(sdd, msg);
+
+       msg->status = status;
+
+       if (msg->complete)
+               msg->complete(msg->context);
+}
+
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+       if (s3c2410_dma_request(sdd->rx_dmach,
+                                       &s3c64xx_spi_dma_client, NULL) < 0) {
+               dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
+               return 0;
+       }
+       s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
+       s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
+                                       sdd->sfr_start + S3C64XX_SPI_RX_DATA);
+
+       if (s3c2410_dma_request(sdd->tx_dmach,
+                                       &s3c64xx_spi_dma_client, NULL) < 0) {
+               dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
+               s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+               return 0;
+       }
+       s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
+       s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
+                                       sdd->sfr_start + S3C64XX_SPI_TX_DATA);
+
+       return 1;
+}
+
+static void s3c64xx_spi_work(struct work_struct *work)
+{
+       struct s3c64xx_spi_driver_data *sdd = container_of(work,
+                                       struct s3c64xx_spi_driver_data, work);
+       unsigned long flags;
+
+       /* Acquire DMA channels */
+       while (!acquire_dma(sdd))
+               msleep(10);
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       while (!list_empty(&sdd->queue)
+                               && !(sdd->state & SUSPND)) {
+
+               struct spi_message *msg;
+
+               msg = container_of(sdd->queue.next, struct spi_message, queue);
+
+               list_del_init(&msg->queue);
+
+               /* Set Xfer busy flag */
+               sdd->state |= SPIBUSY;
+
+               spin_unlock_irqrestore(&sdd->lock, flags);
+
+               handle_msg(sdd, msg);
+
+               spin_lock_irqsave(&sdd->lock, flags);
+
+               sdd->state &= ~SPIBUSY;
+       }
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       /* Free DMA channels */
+       s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
+       s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+}
+
+static int s3c64xx_spi_transfer(struct spi_device *spi,
+                                               struct spi_message *msg)
+{
+       struct s3c64xx_spi_driver_data *sdd;
+       unsigned long flags;
+
+       sdd = spi_master_get_devdata(spi->master);
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       if (sdd->state & SUSPND) {
+               spin_unlock_irqrestore(&sdd->lock, flags);
+               return -ESHUTDOWN;
+       }
+
+       msg->status = -EINPROGRESS;
+       msg->actual_length = 0;
+
+       list_add_tail(&msg->queue, &sdd->queue);
+
+       queue_work(sdd->workqueue, &sdd->work);
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       return 0;
+}
+
+/*
+ * Here we only check the validity of requested configuration
+ * and save the configuration in a local data-structure.
+ * The controller is actually configured only just before we
+ * get a message to transfer.
+ */
+static int s3c64xx_spi_setup(struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_cntrlr_info *sci;
+       struct spi_message *msg;
+       u32 psr, speed;
+       unsigned long flags;
+       int err = 0;
+
+       if (cs == NULL || cs->set_level == NULL) {
+               dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
+               return -ENODEV;
+       }
+
+       sdd = spi_master_get_devdata(spi->master);
+       sci = sdd->cntrlr_info;
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       list_for_each_entry(msg, &sdd->queue, queue) {
+               /* Is some mssg is already queued for this device */
+               if (msg->spi == spi) {
+                       dev_err(&spi->dev,
+                               "setup: attempt while mssg in queue!\n");
+                       spin_unlock_irqrestore(&sdd->lock, flags);
+                       return -EBUSY;
+               }
+       }
+
+       if (sdd->state & SUSPND) {
+               spin_unlock_irqrestore(&sdd->lock, flags);
+               dev_err(&spi->dev,
+                       "setup: SPI-%d not active!\n", spi->master->bus_num);
+               return -ESHUTDOWN;
+       }
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       if (spi->bits_per_word != 8
+                       && spi->bits_per_word != 16
+                       && spi->bits_per_word != 32) {
+               dev_err(&spi->dev, "setup: %dbits/wrd not supported!\n",
+                                                       spi->bits_per_word);
+               err = -EINVAL;
+               goto setup_exit;
+       }
+
+       /* Check if we can provide the requested rate */
+       speed = clk_get_rate(sci->src_clk) / 2 / (0 + 1); /* Max possible */
+
+       if (spi->max_speed_hz > speed)
+               spi->max_speed_hz = speed;
+
+       psr = clk_get_rate(sci->src_clk) / 2 / spi->max_speed_hz - 1;
+       psr &= S3C64XX_SPI_PSR_MASK;
+       if (psr == S3C64XX_SPI_PSR_MASK)
+               psr--;
+
+       speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1);
+       if (spi->max_speed_hz < speed) {
+               if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+                       psr++;
+               } else {
+                       err = -EINVAL;
+                       goto setup_exit;
+               }
+       }
+
+       speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1);
+       if (spi->max_speed_hz >= speed)
+               spi->max_speed_hz = speed;
+       else
+               err = -EINVAL;
+
+setup_exit:
+
+       /* setup() returns with device de-selected */
+       disable_cs(sdd, spi);
+
+       return err;
+}
+
+static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
+{
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       void __iomem *regs = sdd->regs;
+       unsigned int val;
+
+       sdd->cur_speed = 0;
+
+       S3C64XX_SPI_DEACT(sdd);
+
+       /* Disable Interrupts - we use Polling if not DMA mode */
+       writel(0, regs + S3C64XX_SPI_INT_EN);
+
+       writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+                               regs + S3C64XX_SPI_CLK_CFG);
+       writel(0, regs + S3C64XX_SPI_MODE_CFG);
+       writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+       /* Clear any irq pending bits */
+       writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
+                               regs + S3C64XX_SPI_PENDING_CLR);
+
+       writel(0, regs + S3C64XX_SPI_SWAP_CFG);
+
+       val = readl(regs + S3C64XX_SPI_MODE_CFG);
+       val &= ~S3C64XX_SPI_MODE_4BURST;
+       val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+       val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+       writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+       flush_fifo(sdd);
+}
+
+static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+{
+       struct resource *mem_res, *dmatx_res, *dmarx_res;
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_cntrlr_info *sci;
+       struct spi_master *master;
+       int ret;
+
+       if (pdev->id < 0) {
+               dev_err(&pdev->dev,
+                               "Invalid platform device id-%d\n", pdev->id);
+               return -ENODEV;
+       }
+
+       if (pdev->dev.platform_data == NULL) {
+               dev_err(&pdev->dev, "platform_data missing!\n");
+               return -ENODEV;
+       }
+
+       /* Check for availability of necessary resource */
+
+       dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (dmatx_res == NULL) {
+               dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
+               return -ENXIO;
+       }
+
+       dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (dmarx_res == NULL) {
+               dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
+               return -ENXIO;
+       }
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (mem_res == NULL) {
+               dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
+               return -ENXIO;
+       }
+
+       master = spi_alloc_master(&pdev->dev,
+                               sizeof(struct s3c64xx_spi_driver_data));
+       if (master == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+               return -ENOMEM;
+       }
+
+       sci = pdev->dev.platform_data;
+
+       platform_set_drvdata(pdev, master);
+
+       sdd = spi_master_get_devdata(master);
+       sdd->master = master;
+       sdd->cntrlr_info = sci;
+       sdd->pdev = pdev;
+       sdd->sfr_start = mem_res->start;
+       sdd->tx_dmach = dmatx_res->start;
+       sdd->rx_dmach = dmarx_res->start;
+
+       sdd->cur_bpw = 8;
+
+       master->bus_num = pdev->id;
+       master->setup = s3c64xx_spi_setup;
+       master->transfer = s3c64xx_spi_transfer;
+       master->num_chipselect = sci->num_cs;
+       master->dma_alignment = 8;
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+       if (request_mem_region(mem_res->start,
+                       resource_size(mem_res), pdev->name) == NULL) {
+               dev_err(&pdev->dev, "Req mem region failed\n");
+               ret = -ENXIO;
+               goto err0;
+       }
+
+       sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
+       if (sdd->regs == NULL) {
+               dev_err(&pdev->dev, "Unable to remap IO\n");
+               ret = -ENXIO;
+               goto err1;
+       }
+
+       if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
+               dev_err(&pdev->dev, "Unable to config gpio\n");
+               ret = -EBUSY;
+               goto err2;
+       }
+
+       /* Setup clocks */
+       sdd->clk = clk_get(&pdev->dev, "spi");
+       if (IS_ERR(sdd->clk)) {
+               dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
+               ret = PTR_ERR(sdd->clk);
+               goto err3;
+       }
+
+       if (clk_enable(sdd->clk)) {
+               dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
+               ret = -EBUSY;
+               goto err4;
+       }
+
+       if (sci->src_clk_nr == S3C64XX_SPI_SRCCLK_PCLK)
+               sci->src_clk = sdd->clk;
+       else
+               sci->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
+       if (IS_ERR(sci->src_clk)) {
+               dev_err(&pdev->dev,
+                       "Unable to acquire clock '%s'\n", sci->src_clk_name);
+               ret = PTR_ERR(sci->src_clk);
+               goto err5;
+       }
+
+       if (sci->src_clk != sdd->clk && clk_enable(sci->src_clk)) {
+               dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
+                                                       sci->src_clk_name);
+               ret = -EBUSY;
+               goto err6;
+       }
+
+       sdd->workqueue = create_singlethread_workqueue(
+                                               dev_name(master->dev.parent));
+       if (sdd->workqueue == NULL) {
+               dev_err(&pdev->dev, "Unable to create workqueue\n");
+               ret = -ENOMEM;
+               goto err7;
+       }
+
+       /* Setup Deufult Mode */
+       s3c64xx_spi_hwinit(sdd, pdev->id);
+
+       spin_lock_init(&sdd->lock);
+       init_completion(&sdd->xfer_completion);
+       INIT_WORK(&sdd->work, s3c64xx_spi_work);
+       INIT_LIST_HEAD(&sdd->queue);
+
+       if (spi_register_master(master)) {
+               dev_err(&pdev->dev, "cannot register SPI master\n");
+               ret = -EBUSY;
+               goto err8;
+       }
+
+       dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d \
+                                       with %d Slaves attached\n",
+                                       pdev->id, master->num_chipselect);
+       dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\
+                                       \tDMA=[Rx-%d, Tx-%d]\n",
+                                       mem_res->end, mem_res->start,
+                                       sdd->rx_dmach, sdd->tx_dmach);
+
+       return 0;
+
+err8:
+       destroy_workqueue(sdd->workqueue);
+err7:
+       if (sci->src_clk != sdd->clk)
+               clk_disable(sci->src_clk);
+err6:
+       if (sci->src_clk != sdd->clk)
+               clk_put(sci->src_clk);
+err5:
+       clk_disable(sdd->clk);
+err4:
+       clk_put(sdd->clk);
+err3:
+err2:
+       iounmap((void *) sdd->regs);
+err1:
+       release_mem_region(mem_res->start, resource_size(mem_res));
+err0:
+       platform_set_drvdata(pdev, NULL);
+       spi_master_put(master);
+
+       return ret;
+}
+
+static int s3c64xx_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       struct resource *mem_res;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdd->lock, flags);
+       sdd->state |= SUSPND;
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       while (sdd->state & SPIBUSY)
+               msleep(10);
+
+       spi_unregister_master(master);
+
+       destroy_workqueue(sdd->workqueue);
+
+       if (sci->src_clk != sdd->clk)
+               clk_disable(sci->src_clk);
+
+       if (sci->src_clk != sdd->clk)
+               clk_put(sci->src_clk);
+
+       clk_disable(sdd->clk);
+       clk_put(sdd->clk);
+
+       iounmap((void *) sdd->regs);
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem_res->start, resource_size(mem_res));
+
+       platform_set_drvdata(pdev, NULL);
+       spi_master_put(master);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       struct s3c64xx_spi_csinfo *cs;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdd->lock, flags);
+       sdd->state |= SUSPND;
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       while (sdd->state & SPIBUSY)
+               msleep(10);
+
+       /* Disable the clock */
+       if (sci->src_clk != sdd->clk)
+               clk_disable(sci->src_clk);
+
+       clk_disable(sdd->clk);
+
+       sdd->cur_speed = 0; /* Output Clock is stopped */
+
+       return 0;
+}
+
+static int s3c64xx_spi_resume(struct platform_device *pdev)
+{
+       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+       struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+       unsigned long flags;
+
+       sci->cfg_gpio(pdev);
+
+       /* Enable the clock */
+       if (sci->src_clk != sdd->clk)
+               clk_enable(sci->src_clk);
+
+       clk_enable(sdd->clk);
+
+       s3c64xx_spi_hwinit(sdd, pdev->id);
+
+       spin_lock_irqsave(&sdd->lock, flags);
+       sdd->state &= ~SUSPND;
+       spin_unlock_irqrestore(&sdd->lock, flags);
+
+       return 0;
+}
+#else
+#define s3c64xx_spi_suspend    NULL
+#define s3c64xx_spi_resume     NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver s3c64xx_spi_driver = {
+       .driver = {
+               .name   = "s3c64xx-spi",
+               .owner = THIS_MODULE,
+       },
+       .remove = s3c64xx_spi_remove,
+       .suspend = s3c64xx_spi_suspend,
+       .resume = s3c64xx_spi_resume,
+};
+MODULE_ALIAS("platform:s3c64xx-spi");
+
+static int __init s3c64xx_spi_init(void)
+{
+       return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
+}
+module_init(s3c64xx_spi_init);
+
+static void __exit s3c64xx_spi_exit(void)
+{
+       platform_driver_unregister(&s3c64xx_spi_driver);
+}
+module_exit(s3c64xx_spi_exit);
+
+MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
+MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
+MODULE_LICENSE("GPL");
index 7d36720..a65c12f 100644 (file)
@@ -148,7 +148,7 @@ static int sh_sci_spi_probe(struct platform_device *dev)
                ret = -ENOENT;
                goto err1;
        }
-       sp->membase = ioremap(r->start, r->end - r->start + 1);
+       sp->membase = ioremap(r->start, resource_size(r));
        if (!sp->membase) {
                ret = -ENXIO;
                goto err1;
index 19f7562..dfa024b 100644 (file)
@@ -375,12 +375,10 @@ static int __init txx9spi_probe(struct platform_device *dev)
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!res)
                goto exit_busy;
-       if (!devm_request_mem_region(&dev->dev,
-                                    res->start, res->end - res->start + 1,
+       if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
                                     "spi_txx9"))
                goto exit_busy;
-       c->membase = devm_ioremap(&dev->dev,
-                                 res->start, res->end - res->start + 1);
+       c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
        if (!c->membase)
                goto exit_busy;
 
index 9c446e6..ea1bec3 100644 (file)
@@ -53,7 +53,7 @@
 #define SPIDEV_MAJOR                   153     /* assigned */
 #define N_SPI_MINORS                   32      /* ... up to 256 */
 
-static unsigned long   minors[N_SPI_MINORS / BITS_PER_LONG];
+static DECLARE_BITMAP(minors, N_SPI_MINORS);
 
 
 /* Bit masks for spi_device.mode management.  Note that incorrect
@@ -558,7 +558,7 @@ static struct class *spidev_class;
 
 /*-------------------------------------------------------------------------*/
 
-static int spidev_probe(struct spi_device *spi)
+static int __devinit spidev_probe(struct spi_device *spi)
 {
        struct spidev_data      *spidev;
        int                     status;
@@ -607,7 +607,7 @@ static int spidev_probe(struct spi_device *spi)
        return status;
 }
 
-static int spidev_remove(struct spi_device *spi)
+static int __devexit spidev_remove(struct spi_device *spi)
 {
        struct spidev_data      *spidev = spi_get_drvdata(spi);
 
@@ -629,7 +629,7 @@ static int spidev_remove(struct spi_device *spi)
        return 0;
 }
 
-static struct spi_driver spidev_spi = {
+static struct spi_driver spidev_spi_driver = {
        .driver = {
                .name =         "spidev",
                .owner =        THIS_MODULE,
@@ -661,14 +661,14 @@ static int __init spidev_init(void)
 
        spidev_class = class_create(THIS_MODULE, "spidev");
        if (IS_ERR(spidev_class)) {
-               unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+               unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
                return PTR_ERR(spidev_class);
        }
 
-       status = spi_register_driver(&spidev_spi);
+       status = spi_register_driver(&spidev_spi_driver);
        if (status < 0) {
                class_destroy(spidev_class);
-               unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+               unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
        }
        return status;
 }
@@ -676,9 +676,9 @@ module_init(spidev_init);
 
 static void __exit spidev_exit(void)
 {
-       spi_unregister_driver(&spidev_spi);
+       spi_unregister_driver(&spidev_spi_driver);
        class_destroy(spidev_class);
-       unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+       unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 }
 module_exit(spidev_exit);
 
index f0b86f0..fd677f0 100644 (file)
@@ -29,7 +29,6 @@
  * driver requests - some may support multiple options */
 
 
-#include <linux/autoconf.h>
 #include "iio.h"
 #include "ring_generic.h"
 
index 536e238..638ad6b 100644 (file)
@@ -1,7 +1,8 @@
 config OCTEON_ETHERNET
        tristate "Cavium Networks Octeon Ethernet support"
        depends on CPU_CAVIUM_OCTEON
-       select MII
+       select PHYLIB
+       select MDIO_OCTEON
        help
          This driver supports the builtin ethernet ports on Cavium
          Networks' products in the Octeon family. This driver supports the
index 31a58e5..05a5cc0 100644 (file)
@@ -26,7 +26,8 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
+
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
 #include "ethernet-defines.h"
 #include "octeon-ethernet.h"
 #include "ethernet-mdio.h"
+#include "ethernet-util.h"
 
 #include "cvmx-helper-board.h"
 
 #include "cvmx-smix-defs.h"
 
-DECLARE_MUTEX(mdio_sem);
-
-/**
- * Perform an MII read. Called by the generic MII routines
- *
- * @dev:      Device to perform read for
- * @phy_id:   The MII phy id
- * @location: Register location to read
- * Returns Result from the read or zero on failure
- */
-static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location)
-{
-       union cvmx_smix_cmd smi_cmd;
-       union cvmx_smix_rd_dat smi_rd;
-
-       smi_cmd.u64 = 0;
-       smi_cmd.s.phy_op = 1;
-       smi_cmd.s.phy_adr = phy_id;
-       smi_cmd.s.reg_adr = location;
-       cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
-
-       do {
-               if (!in_interrupt())
-                       yield();
-               smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0));
-       } while (smi_rd.s.pending);
-
-       if (smi_rd.s.val)
-               return smi_rd.s.dat;
-       else
-               return 0;
-}
-
-static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id,
-                                  int location)
-{
-       return 0xffff;
-}
-
-/**
- * Perform an MII write. Called by the generic MII routines
- *
- * @dev:      Device to perform write for
- * @phy_id:   The MII phy id
- * @location: Register location to write
- * @val:      Value to write
- */
-static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location,
-                              int val)
-{
-       union cvmx_smix_cmd smi_cmd;
-       union cvmx_smix_wr_dat smi_wr;
-
-       smi_wr.u64 = 0;
-       smi_wr.s.dat = val;
-       cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64);
-
-       smi_cmd.u64 = 0;
-       smi_cmd.s.phy_op = 0;
-       smi_cmd.s.phy_adr = phy_id;
-       smi_cmd.s.reg_adr = location;
-       cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
-
-       do {
-               if (!in_interrupt())
-                       yield();
-               smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0));
-       } while (smi_wr.s.pending);
-}
-
-static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id,
-                                    int location, int val)
-{
-}
-
 static void cvm_oct_get_drvinfo(struct net_device *dev,
                                struct ethtool_drvinfo *info)
 {
@@ -125,49 +52,37 @@ static void cvm_oct_get_drvinfo(struct net_device *dev,
 static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
-       int ret;
 
-       down(&mdio_sem);
-       ret = mii_ethtool_gset(&priv->mii_info, cmd);
-       up(&mdio_sem);
+       if (priv->phydev)
+               return phy_ethtool_gset(priv->phydev, cmd);
 
-       return ret;
+       return -EINVAL;
 }
 
 static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
-       int ret;
 
-       down(&mdio_sem);
-       ret = mii_ethtool_sset(&priv->mii_info, cmd);
-       up(&mdio_sem);
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       if (priv->phydev)
+               return phy_ethtool_sset(priv->phydev, cmd);
 
-       return ret;
+       return -EINVAL;
 }
 
 static int cvm_oct_nway_reset(struct net_device *dev)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
-       int ret;
 
-       down(&mdio_sem);
-       ret = mii_nway_restart(&priv->mii_info);
-       up(&mdio_sem);
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
 
-       return ret;
-}
+       if (priv->phydev)
+               return phy_start_aneg(priv->phydev);
 
-static u32 cvm_oct_get_link(struct net_device *dev)
-{
-       struct octeon_ethernet *priv = netdev_priv(dev);
-       u32 ret;
-
-       down(&mdio_sem);
-       ret = mii_link_ok(&priv->mii_info);
-       up(&mdio_sem);
-
-       return ret;
+       return -EINVAL;
 }
 
 const struct ethtool_ops cvm_oct_ethtool_ops = {
@@ -175,7 +90,7 @@ const struct ethtool_ops cvm_oct_ethtool_ops = {
        .get_settings = cvm_oct_get_settings,
        .set_settings = cvm_oct_set_settings,
        .nway_reset = cvm_oct_nway_reset,
-       .get_link = cvm_oct_get_link,
+       .get_link = ethtool_op_get_link,
        .get_sg = ethtool_op_get_sg,
        .get_tx_csum = ethtool_op_get_tx_csum,
 };
@@ -191,41 +106,78 @@ const struct ethtool_ops cvm_oct_ethtool_ops = {
 int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
-       struct mii_ioctl_data *data = if_mii(rq);
-       unsigned int duplex_chg;
-       int ret;
 
-       down(&mdio_sem);
-       ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg);
-       up(&mdio_sem);
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       if (!priv->phydev)
+               return -EINVAL;
+
+       return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+}
 
-       return ret;
+static void cvm_oct_adjust_link(struct net_device *dev)
+{
+       struct octeon_ethernet *priv = netdev_priv(dev);
+       cvmx_helper_link_info_t link_info;
+
+       if (priv->last_link != priv->phydev->link) {
+               priv->last_link = priv->phydev->link;
+               link_info.u64 = 0;
+               link_info.s.link_up = priv->last_link ? 1 : 0;
+               link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
+               link_info.s.speed = priv->phydev->speed;
+               cvmx_helper_link_set( priv->port, link_info);
+               if (priv->last_link) {
+                       netif_carrier_on(dev);
+                       if (priv->queue != -1)
+                               DEBUGPRINT("%s: %u Mbps %s duplex, "
+                                          "port %2d, queue %2d\n",
+                                          dev->name, priv->phydev->speed,
+                                          priv->phydev->duplex ?
+                                               "Full" : "Half",
+                                          priv->port, priv->queue);
+                       else
+                               DEBUGPRINT("%s: %u Mbps %s duplex, "
+                                          "port %2d, POW\n",
+                                          dev->name, priv->phydev->speed,
+                                          priv->phydev->duplex ?
+                                               "Full" : "Half",
+                                          priv->port);
+               } else {
+                       netif_carrier_off(dev);
+                       DEBUGPRINT("%s: Link down\n", dev->name);
+               }
+       }
 }
 
+
 /**
- * Setup the MDIO device structures
+ * Setup the PHY
  *
  * @dev:    Device to setup
  *
  * Returns Zero on success, negative on failure
  */
-int cvm_oct_mdio_setup_device(struct net_device *dev)
+int cvm_oct_phy_setup_device(struct net_device *dev)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
-       int phy_id = cvmx_helper_board_get_mii_address(priv->port);
-       if (phy_id != -1) {
-               priv->mii_info.dev = dev;
-               priv->mii_info.phy_id = phy_id;
-               priv->mii_info.phy_id_mask = 0xff;
-               priv->mii_info.supports_gmii = 1;
-               priv->mii_info.reg_num_mask = 0x1f;
-               priv->mii_info.mdio_read = cvm_oct_mdio_read;
-               priv->mii_info.mdio_write = cvm_oct_mdio_write;
-       } else {
-               /* Supply dummy MDIO routines so the kernel won't crash
-                  if the user tries to read them */
-               priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read;
-               priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write;
+
+       int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
+       if (phy_addr != -1) {
+               char phy_id[20];
+
+               snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+
+               priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
+                                       PHY_INTERFACE_MODE_GMII);
+
+               if (IS_ERR(priv->phydev)) {
+                       priv->phydev = NULL;
+                       return -1;
+               }
+               priv->last_link = 0;
+               phy_start_aneg(priv->phydev);
        }
        return 0;
 }
index b3328ae..55d0614 100644 (file)
@@ -43,4 +43,4 @@
 
 extern const struct ethtool_ops cvm_oct_ethtool_ops;
 int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int cvm_oct_mdio_setup_device(struct net_device *dev);
+int cvm_oct_phy_setup_device(struct net_device *dev);
index 8fa88fc..16308d4 100644 (file)
@@ -25,7 +25,6 @@
  * Contact Cavium Networks for more information
 **********************************************************************/
 #include <linux/kernel.h>
-#include <linux/mii.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <net/dst.h>
 #include "cvmx-helper.h"
 #include "cvmx-pip.h"
 
-static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev,
-                                                   int phy_id, int offset)
-{
-       struct octeon_ethernet *priv = netdev_priv(dev);
-
-       priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset);
-       return ((uint64_t) priv->mii_info.
-               mdio_read(dev, phy_id,
-                         0x1e) << 16) | (uint64_t) priv->mii_info.
-           mdio_read(dev, phy_id, 0x1f);
-}
-
-static int cvm_oct_stats_switch_show(struct seq_file *m, void *v)
-{
-       static const int ports[] = { 0, 1, 2, 3, 9, -1 };
-       struct net_device *dev = cvm_oct_device[0];
-       int index = 0;
-
-       while (ports[index] != -1) {
-
-               /* Latch port */
-               struct octeon_ethernet *priv = netdev_priv(dev);
-
-               priv->mii_info.mdio_write(dev, 0x1b, 0x1d,
-                                         0xdc00 | ports[index]);
-               seq_printf(m, "\nSwitch Port %d\n", ports[index]);
-               seq_printf(m, "InGoodOctets:   %12llu\t"
-                          "OutOctets:      %12llu\t"
-                          "64 Octets:      %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b,
-                                                    0x00) |
-                          (cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32),
-                          cvm_oct_stats_read_switch(dev, 0x1b,
-                                                    0x0E) |
-                          (cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x08));
-
-               seq_printf(m, "InBadOctets:    %12llu\t"
-                          "OutUnicast:     %12llu\t"
-                          "65-127 Octets:  %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x02),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x10),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x09));
-
-               seq_printf(m, "InUnicast:      %12llu\t"
-                          "OutBroadcasts:  %12llu\t"
-                          "128-255 Octets: %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x04),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x13),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x0A));
-
-               seq_printf(m, "InBroadcasts:   %12llu\t"
-                          "OutMulticasts:  %12llu\t"
-                          "256-511 Octets: %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x06),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x12),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x0B));
-
-               seq_printf(m, "InMulticasts:   %12llu\t"
-                          "OutPause:       %12llu\t"
-                          "512-1023 Octets:%12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x07),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x15),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x0C));
-
-               seq_printf(m, "InPause:        %12llu\t"
-                          "Excessive:      %12llu\t"
-                          "1024-Max Octets:%12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x16),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x11),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x0D));
-
-               seq_printf(m, "InUndersize:    %12llu\t"
-                          "Collisions:     %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x18),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1E));
-
-               seq_printf(m, "InFragments:    %12llu\t"
-                          "Deferred:       %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x19),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x05));
-
-               seq_printf(m, "InOversize:     %12llu\t"
-                          "Single:         %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1A),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x14));
-
-               seq_printf(m, "InJabber:       %12llu\t"
-                          "Multiple:       %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1B),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x17));
-
-               seq_printf(m, "In RxErr:       %12llu\t"
-                          "OutFCSErr:      %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1C),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x03));
-
-               seq_printf(m, "InFCSErr:       %12llu\t"
-                          "Late:           %12llu\n",
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1D),
-                          cvm_oct_stats_read_switch(dev, 0x1b, 0x1F));
-               index++;
-       }
-       return 0;
-}
-
 /**
  * User is reading /proc/octeon_ethernet_stats
  *
@@ -215,11 +108,6 @@ static int cvm_oct_stats_show(struct seq_file *m, void *v)
                }
        }
 
-       if (cvm_oct_device[0]) {
-               priv = netdev_priv(cvm_oct_device[0]);
-               if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
-                       cvm_oct_stats_switch_show(m, v);
-       }
        return 0;
 }
 
index fbaa465..3820f1e 100644 (file)
@@ -147,32 +147,36 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
                cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
                               gmxx_rxx_int_reg.u64);
        }
-
-       link_info = cvmx_helper_link_autoconf(priv->port);
-       priv->link_info = link_info.u64;
+       if (priv->phydev == NULL) {
+               link_info = cvmx_helper_link_autoconf(priv->port);
+               priv->link_info = link_info.u64;
+       }
        spin_unlock_irqrestore(&global_register_lock, flags);
 
-       /* Tell Linux */
-       if (link_info.s.link_up) {
-
-               if (!netif_carrier_ok(dev))
-                       netif_carrier_on(dev);
-               if (priv->queue != -1)
-                       DEBUGPRINT
-                           ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
-                            dev->name, link_info.s.speed,
-                            (link_info.s.full_duplex) ? "Full" : "Half",
-                            priv->port, priv->queue);
-               else
-                       DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
-                                  dev->name, link_info.s.speed,
-                                  (link_info.s.full_duplex) ? "Full" : "Half",
-                                  priv->port);
-       } else {
-
-               if (netif_carrier_ok(dev))
-                       netif_carrier_off(dev);
-               DEBUGPRINT("%s: Link down\n", dev->name);
+       if (priv->phydev == NULL) {
+               /* Tell core. */
+               if (link_info.s.link_up) {
+                       if (!netif_carrier_ok(dev))
+                               netif_carrier_on(dev);
+                       if (priv->queue != -1)
+                               DEBUGPRINT("%s: %u Mbps %s duplex, "
+                                          "port %2d, queue %2d\n",
+                                          dev->name, link_info.s.speed,
+                                          (link_info.s.full_duplex) ?
+                                               "Full" : "Half",
+                                          priv->port, priv->queue);
+                       else
+                               DEBUGPRINT("%s: %u Mbps %s duplex, "
+                                          "port %2d, POW\n",
+                                          dev->name, link_info.s.speed,
+                                          (link_info.s.full_duplex) ?
+                                               "Full" : "Half",
+                                          priv->port);
+               } else {
+                       if (netif_carrier_ok(dev))
+                               netif_carrier_off(dev);
+                       DEBUGPRINT("%s: Link down\n", dev->name);
+               }
        }
 }
 
index 2b54996..6061d01 100644 (file)
@@ -113,7 +113,7 @@ int cvm_oct_sgmii_init(struct net_device *dev)
        struct octeon_ethernet *priv = netdev_priv(dev);
        cvm_oct_common_init(dev);
        dev->netdev_ops->ndo_stop(dev);
-       if (!octeon_is_simulation())
+       if (!octeon_is_simulation() && priv->phydev == NULL)
                priv->poll = cvm_oct_sgmii_poll;
 
        /* FIXME: Need autoneg logic */
index 0c2e7cc..ee3dc41 100644 (file)
@@ -112,7 +112,7 @@ int cvm_oct_xaui_init(struct net_device *dev)
        struct octeon_ethernet *priv = netdev_priv(dev);
        cvm_oct_common_init(dev);
        dev->netdev_ops->ndo_stop(dev);
-       if (!octeon_is_simulation())
+       if (!octeon_is_simulation() && priv->phydev == NULL)
                priv->poll = cvm_oct_xaui_poll;
 
        return 0;
index 492c502..4cfd4b1 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include <net/dst.h>
 
@@ -132,8 +132,6 @@ static struct timer_list cvm_oct_poll_timer;
  */
 struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
 
-extern struct semaphore mdio_sem;
-
 /**
  * Periodic timer tick for slow management operations
  *
@@ -160,13 +158,8 @@ static void cvm_do_timer(unsigned long arg)
                goto out;
 
        priv = netdev_priv(cvm_oct_device[port]);
-       if (priv->poll) {
-               /* skip polling if we don't get the lock */
-               if (!down_trylock(&mdio_sem)) {
-                       priv->poll(cvm_oct_device[port]);
-                       up(&mdio_sem);
-               }
-       }
+       if (priv->poll)
+               priv->poll(cvm_oct_device[port]);
 
        queues_per_port = cvmx_pko_get_num_queues(port);
        /* Drain any pending packets in the free list */
@@ -524,7 +517,7 @@ int cvm_oct_common_init(struct net_device *dev)
        dev->features |= NETIF_F_LLTX;
        SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
 
-       cvm_oct_mdio_setup_device(dev);
+       cvm_oct_phy_setup_device(dev);
        dev->netdev_ops->ndo_set_mac_address(dev, &sa);
        dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
 
@@ -540,7 +533,10 @@ int cvm_oct_common_init(struct net_device *dev)
 
 void cvm_oct_common_uninit(struct net_device *dev)
 {
-       /* Currently nothing to do */
+       struct octeon_ethernet *priv = netdev_priv(dev);
+
+       if (priv->phydev)
+               phy_disconnect(priv->phydev);
 }
 
 static const struct net_device_ops cvm_oct_npi_netdev_ops = {
@@ -627,6 +623,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
 #endif
 };
 
+extern void octeon_mdiobus_force_mod_depencency(void);
+
 /**
  * Module/ driver initialization. Creates the linux network
  * devices.
@@ -640,6 +638,7 @@ static int __init cvm_oct_init_module(void)
        int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
        int qos;
 
+       octeon_mdiobus_force_mod_depencency();
        pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
 
        if (OCTEON_IS_MODEL(OCTEON_CN52XX))
index 3aef987..402a15b 100644 (file)
@@ -50,9 +50,9 @@ struct octeon_ethernet {
        /* List of outstanding tx buffers per queue */
        struct sk_buff_head tx_free_list[16];
        /* Device statistics */
-       struct net_device_stats stats
-;      /* Generic MII info structure */
-       struct mii_if_info mii_info;
+       struct net_device_stats stats;
+       struct phy_device *phydev;
+       unsigned int last_link;
        /* Last negotiated link state */
        uint64_t link_info;
        /* Called periodically to check link status */
index 4ce399b..f98a524 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 #include <linux/io.h>
 #include <asm/uaccess.h>
index 12f1ad2..74d07f4 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
-#include <mach/usb.h>
+#include <plat/usb.h>
 
 /*
  * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
index 2051c9d..b7687c5 100644 (file)
@@ -2245,9 +2245,6 @@ static int ext_setcolreg(unsigned int regno, unsigned int red,
        if (regno > 255)
                return 1;
 
-       if (regno > 255)
-               return 1;
-
        switch (external_card_type) {
        case IS_VGA:
                OUTB(0x3c8, regno);
index 4c10ede..86d95c2 100644 (file)
@@ -85,7 +85,7 @@ static int adp5520_bl_get_brightness(struct backlight_device *bl)
        return error ? data->current_brightness : reg_val;
 }
 
-static struct backlight_ops adp5520_bl_ops = {
+static const struct backlight_ops adp5520_bl_ops = {
        .update_status  = adp5520_bl_update_status,
        .get_brightness = adp5520_bl_get_brightness,
 };
index 2c3bdfc..d769b0b 100644 (file)
@@ -61,7 +61,7 @@ static int adx_backlight_check_fb(struct fb_info *fb)
        return 1;
 }
 
-static struct backlight_ops adx_backlight_ops = {
+static const struct backlight_ops adx_backlight_ops = {
        .options = 0,
        .update_status = adx_backlight_update_status,
        .get_brightness = adx_backlight_get_brightness,
index 2cf7ba5..f625ffc 100644 (file)
@@ -113,7 +113,7 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
        return pwm_channel_enable(&pwmbl->pwmc);
 }
 
-static struct backlight_ops atmel_pwm_bl_ops = {
+static const struct backlight_ops atmel_pwm_bl_ops = {
        .get_brightness = atmel_pwm_bl_get_intensity,
        .update_status  = atmel_pwm_bl_set_intensity,
 };
index 6615ac7..18829cf 100644 (file)
@@ -269,7 +269,7 @@ EXPORT_SYMBOL(backlight_force_update);
  * ERR_PTR() or a pointer to the newly allocated device.
  */
 struct backlight_device *backlight_device_register(const char *name,
-               struct device *parent, void *devdata, struct backlight_ops *ops)
+               struct device *parent, void *devdata, const struct backlight_ops *ops)
 {
        struct backlight_device *new_bd;
        int rc;
index 9677494..b4bcf80 100644 (file)
@@ -451,7 +451,7 @@ void corgi_lcd_limit_intensity(int limit)
 }
 EXPORT_SYMBOL(corgi_lcd_limit_intensity);
 
-static struct backlight_ops corgi_bl_ops = {
+static const struct backlight_ops corgi_bl_ops = {
        .get_brightness = corgi_bl_get_intensity,
        .update_status  = corgi_bl_update_status,
 };
index b9fe62b..da86db4 100644 (file)
@@ -108,7 +108,7 @@ static int cr_backlight_get_intensity(struct backlight_device *bd)
        return intensity;
 }
 
-static struct backlight_ops cr_backlight_ops = {
+static const struct backlight_ops cr_backlight_ops = {
        .get_brightness = cr_backlight_get_intensity,
        .update_status = cr_backlight_set_intensity,
 };
@@ -201,7 +201,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
        if (IS_ERR(ldp)) {
                backlight_device_unregister(bdp);
                pci_dev_put(lpc_dev);
-               return PTR_ERR(bdp);
+               return PTR_ERR(ldp);
        }
 
        pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
index f2d76da..74cdc64 100644 (file)
@@ -95,7 +95,7 @@ static int da903x_backlight_get_brightness(struct backlight_device *bl)
        return data->current_brightness;
 }
 
-static struct backlight_ops da903x_backlight_ops = {
+static const struct backlight_ops da903x_backlight_ops = {
        .update_status  = da903x_backlight_update_status,
        .get_brightness = da903x_backlight_get_brightness,
 };
index 6d27f62..e6d348e 100644 (file)
@@ -70,7 +70,7 @@ void corgibl_limit_intensity(int limit)
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
-static struct backlight_ops genericbl_ops = {
+static const struct backlight_ops genericbl_ops = {
        .options = BL_CORE_SUSPENDRESUME,
        .get_brightness = genericbl_get_intensity,
        .update_status  = genericbl_send_intensity,
index 7fb4eef..f7cc528 100644 (file)
@@ -98,7 +98,7 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
        return current_intensity;
 }
 
-static struct backlight_ops hp680bl_ops = {
+static const struct backlight_ops hp680bl_ops = {
        .get_brightness = hp680bl_get_intensity,
        .update_status  = hp680bl_set_intensity,
 };
index 7aed256..db9071f 100644 (file)
@@ -93,7 +93,7 @@ out:
        return ret;
 }
 
-static struct backlight_ops jornada_bl_ops = {
+static const struct backlight_ops jornada_bl_ops = {
        .get_brightness = jornada_bl_get_brightness,
        .update_status = jornada_bl_update_status,
        .options = BL_CORE_SUSPENDRESUME,
index a38fda1..939e7b8 100644 (file)
@@ -134,7 +134,7 @@ static int kb3886bl_get_intensity(struct backlight_device *bd)
        return kb3886bl_intensity;
 }
 
-static struct backlight_ops kb3886bl_ops = {
+static const struct backlight_ops kb3886bl_ops = {
        .get_brightness = kb3886bl_get_intensity,
        .update_status  = kb3886bl_send_intensity,
 };
index 6b488b8..00a9591 100644 (file)
@@ -141,7 +141,7 @@ static int locomolcd_get_intensity(struct backlight_device *bd)
        return current_intensity;
 }
 
-static struct backlight_ops locomobl_data = {
+static const struct backlight_ops locomobl_data = {
        .get_brightness = locomolcd_get_intensity,
        .update_status  = locomolcd_set_intensity,
 };
index 9edb8d7..2e78b07 100644 (file)
@@ -33,7 +33,7 @@ struct dmi_match_data {
        unsigned long iostart;
        unsigned long iolen;
        /* Backlight operations structure. */
-       struct backlight_ops backlight_ops;
+       const struct backlight_ops backlight_ops;
 };
 
 /* Module parameters. */
@@ -220,6 +220,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
        },
        {
                .callback       = mbp_dmi_match,
+               .ident          = "MacBookPro 5,3",
+               .matches        = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
+               },
+               .driver_data    = (void *)&nvidia_chipset_data,
+       },
+       {
+               .callback       = mbp_dmi_match,
+               .ident          = "MacBookPro 5,4",
+               .matches        = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
+               },
+               .driver_data    = (void *)&nvidia_chipset_data,
+       },
+       {
+               .callback       = mbp_dmi_match,
                .ident          = "MacBookPro 5,5",
                .matches        = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
index 8693e5f..409ca96 100644 (file)
@@ -125,7 +125,7 @@ static int omapbl_get_intensity(struct backlight_device *dev)
        return bl->current_intensity;
 }
 
-static struct backlight_ops omapbl_ops = {
+static const struct backlight_ops omapbl_ops = {
        .get_brightness = omapbl_get_intensity,
        .update_status  = omapbl_update_status,
 };
index 9edaf24..075786e 100644 (file)
@@ -54,7 +54,7 @@ static int progearbl_get_intensity(struct backlight_device *bd)
        return intensity - HW_LEVEL_MIN;
 }
 
-static struct backlight_ops progearbl_ops = {
+static const struct backlight_ops progearbl_ops = {
        .get_brightness = progearbl_get_intensity,
        .update_status = progearbl_set_intensity,
 };
index 8871662..9d2ec2a 100644 (file)
 
 struct pwm_bl_data {
        struct pwm_device       *pwm;
+       struct device           *dev;
        unsigned int            period;
-       int                     (*notify)(int brightness);
+       int                     (*notify)(struct device *,
+                                         int brightness);
 };
 
 static int pwm_backlight_update_status(struct backlight_device *bl)
@@ -39,7 +41,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
                brightness = 0;
 
        if (pb->notify)
-               brightness = pb->notify(brightness);
+               brightness = pb->notify(pb->dev, brightness);
 
        if (brightness == 0) {
                pwm_config(pb->pwm, 0, pb->period);
@@ -56,7 +58,7 @@ static int pwm_backlight_get_brightness(struct backlight_device *bl)
        return bl->props.brightness;
 }
 
-static struct backlight_ops pwm_backlight_ops = {
+static const struct backlight_ops pwm_backlight_ops = {
        .update_status  = pwm_backlight_update_status,
        .get_brightness = pwm_backlight_get_brightness,
 };
@@ -88,6 +90,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 
        pb->period = data->pwm_period_ns;
        pb->notify = data->notify;
+       pb->dev = &pdev->dev;
 
        pb->pwm = pwm_request(data->pwm_id, "backlight");
        if (IS_ERR(pb->pwm)) {
@@ -146,7 +149,7 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
        struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
 
        if (pb->notify)
-               pb->notify(0);
+               pb->notify(pb->dev, 0);
        pwm_config(pb->pwm, 0, pb->period);
        pwm_disable(pb->pwm);
        return 0;
index 43edbad..e14ce4d 100644 (file)
@@ -72,7 +72,7 @@ static int tosa_bl_get_brightness(struct backlight_device *dev)
        return props->brightness;
 }
 
-static struct backlight_ops bl_ops = {
+static const struct backlight_ops bl_ops = {
        .get_brightness         = tosa_bl_get_brightness,
        .update_status          = tosa_bl_update_status,
 };
index 467bdb7..e32add3 100644 (file)
@@ -112,7 +112,7 @@ static int wm831x_backlight_get_brightness(struct backlight_device *bl)
        return data->current_brightness;
 }
 
-static struct backlight_ops wm831x_backlight_ops = {
+static const struct backlight_ops wm831x_backlight_ops = {
        .options = BL_CORE_SUSPENDRESUME,
        .update_status  = wm831x_backlight_update_status,
        .get_brightness = wm831x_backlight_get_brightness,
index 5bb7f6f..0f5952c 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/gpio.h>
 #include <plat/mux.h>
@@ -59,7 +59,7 @@
 #define TWL4030_VPLL2_DEV_GRP           0x33
 #define TWL4030_VPLL2_DEDICATED         0x36
 
-#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
+#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
 
 
 static int ldp_panel_init(struct lcd_panel *panel,
index 006c2fe..7e7a65c 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <plat/mux.h>
 #include <asm/mach-types.h>
@@ -61,9 +61,9 @@ static int omap2evm_panel_init(struct lcd_panel *panel,
        gpio_direction_output(LCD_PANEL_LR, 1);
        gpio_direction_output(LCD_PANEL_UD, 1);
 
-       twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
-       twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
-       twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
+       twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
+       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
+       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
        bklight_level = 100;
 
        return 0;
@@ -101,7 +101,7 @@ static int omap2evm_bklight_setlevel(struct lcd_panel *panel,
        u8 c;
        if ((level >= 0) && (level <= 100)) {
                c = (125 * (100 - level)) / 100 + 2;
-               twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
+               twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
                bklight_level = level;
        }
        return 0;
index fc503d8..ca75cc2 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <plat/mux.h>
 #include <plat/mux.h>
index ae2edc4..06840da 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <plat/mux.h>
 #include <asm/mach-types.h>
@@ -63,9 +63,9 @@ static int omap3evm_panel_init(struct lcd_panel *panel,
        gpio_direction_output(LCD_PANEL_LR, 1);
        gpio_direction_output(LCD_PANEL_UD, 1);
 
-       twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
-       twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
-       twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
+       twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
+       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
+       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
        bklight_level = 100;
 
        return 0;
@@ -102,7 +102,7 @@ static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
        u8 c;
        if ((level >= 0) && (level <= 100)) {
                c = (125 * (100 - level)) / 100 + 2;
-               twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
+               twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
                bklight_level = level;
        }
        return 0;
index 56ee192..564933f 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/gpio.h>
 #include <plat/mux.h>
index 10d8c4b..d8df17a 100644 (file)
@@ -680,7 +680,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                if (!viafb_gamma_table)
                        return -ENOMEM;
                if (copy_from_user(viafb_gamma_table, argp,
-                               sizeof(viafb_gamma_table))) {
+                               256 * sizeof(u32))) {
                        kfree(viafb_gamma_table);
                        return -EFAULT;
                }
@@ -694,7 +694,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                        return -ENOMEM;
                viafb_get_gamma_table(viafb_gamma_table);
                if (copy_to_user(argp, viafb_gamma_table,
-                       sizeof(viafb_gamma_table))) {
+                       256 * sizeof(u32))) {
                        kfree(viafb_gamma_table);
                        return -EFAULT;
                }
index d958b76..da84fd0 100644 (file)
@@ -815,16 +815,6 @@ config PNX833X_WDT
          timer has expired and no process has written to /dev/watchdog during
          that time.
 
-config WDT_RM9K_GPI
-       tristate "RM9000/GPI hardware watchdog"
-       depends on CPU_RM9000
-       help
-         Watchdog implementation using the GPI hardware found on
-         PMC-Sierra RM9xxx CPUs.
-
-         To compile this driver as a module, choose M here: the
-         module will be called rm9k_wdt.
-
 config SIBYTE_WDOG
        tristate "Sibyte SoC hardware watchdog"
        depends on CPU_SB1
index 89c045d..475c611 100644 (file)
@@ -109,7 +109,6 @@ obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
 obj-$(CONFIG_INDYDOG) += indydog.o
 obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
 obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
-obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
 obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
 obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
 obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
deleted file mode 100644 (file)
index bb66958..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- *  Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx
- *  chips.
- *
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <asm/atomic.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <rm9k_wdt.h>
-
-
-#define CLOCK                  125000000
-#define MAX_TIMEOUT_SECONDS    32
-#define CPCCR                  0x0080
-#define CPGIG1SR               0x0044
-#define CPGIG1ER               0x0054
-
-
-/* Function prototypes */
-static irqreturn_t wdt_gpi_irqhdl(int, void *);
-static void wdt_gpi_start(void);
-static void wdt_gpi_stop(void);
-static void wdt_gpi_set_timeout(unsigned int);
-static int wdt_gpi_open(struct inode *, struct file *);
-static int wdt_gpi_release(struct inode *, struct file *);
-static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t,
-                                                               loff_t *);
-static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
-static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
-static const struct resource *wdt_gpi_get_resource(struct platform_device *,
-                                               const char *, unsigned int);
-static int __init wdt_gpi_probe(struct platform_device *);
-static int __exit wdt_gpi_remove(struct platform_device *);
-
-
-static const char wdt_gpi_name[] = "wdt_gpi";
-static atomic_t opencnt;
-static int expect_close;
-static int locked;
-
-
-/* These are set from device resources */
-static void __iomem *wd_regs;
-static unsigned int wd_irq, wd_ctr;
-
-
-/* Module arguments */
-static int timeout = MAX_TIMEOUT_SECONDS;
-module_param(timeout, int, 0444);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
-
-static unsigned long resetaddr = 0xbffdc200;
-module_param(resetaddr, ulong, 0444);
-MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset");
-
-static unsigned long flagaddr = 0xbffdc104;
-module_param(flagaddr, ulong, 0444);
-MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to");
-
-static int powercycle;
-module_param(powercycle, bool, 0444);
-MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, bool, 0444);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
-
-
-/* Kernel interfaces */
-static const struct file_operations fops = {
-       .owner          = THIS_MODULE,
-       .open           = wdt_gpi_open,
-       .release        = wdt_gpi_release,
-       .write          = wdt_gpi_write,
-       .unlocked_ioctl = wdt_gpi_ioctl,
-};
-
-static struct miscdevice miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = wdt_gpi_name,
-       .fops           = &fops,
-};
-
-static struct notifier_block wdt_gpi_shutdown = {
-       .notifier_call  = wdt_gpi_notify,
-};
-
-
-/* Interrupt handler */
-static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt)
-{
-       if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
-               return IRQ_NONE;
-       __raw_writel(0x1, wd_regs + 0x0008);
-
-
-       printk(KERN_CRIT "%s: watchdog expired - resetting system\n",
-               wdt_gpi_name);
-
-       *(volatile char *) flagaddr |= 0x01;
-       *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2;
-       iob();
-       while (1)
-               cpu_relax();
-}
-
-
-/* Watchdog functions */
-static void wdt_gpi_start(void)
-{
-       u32 reg;
-
-       lock_titan_regs();
-       reg = titan_readl(CPGIG1ER);
-       titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER);
-       iob();
-       unlock_titan_regs();
-}
-
-static void wdt_gpi_stop(void)
-{
-       u32 reg;
-
-       lock_titan_regs();
-       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-       titan_writel(reg, CPCCR);
-       reg = titan_readl(CPGIG1ER);
-       titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER);
-       iob();
-       unlock_titan_regs();
-}
-
-static void wdt_gpi_set_timeout(unsigned int to)
-{
-       u32 reg;
-       const u32 wdval = (to * CLOCK) & ~0x0000000f;
-
-       lock_titan_regs();
-       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-       titan_writel(reg, CPCCR);
-       wmb();
-       __raw_writel(wdval, wd_regs + 0x0000);
-       wmb();
-       titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR);
-       wmb();
-       titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR);
-       iob();
-       unlock_titan_regs();
-}
-
-
-/* /dev/watchdog operations */
-static int wdt_gpi_open(struct inode *inode, struct file *file)
-{
-       int res;
-
-       if (unlikely(atomic_dec_if_positive(&opencnt) < 0))
-               return -EBUSY;
-
-       expect_close = 0;
-       if (locked) {
-               module_put(THIS_MODULE);
-               free_irq(wd_irq, &miscdev);
-               locked = 0;
-       }
-
-       res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
-                         wdt_gpi_name, &miscdev);
-       if (unlikely(res))
-               return res;
-
-       wdt_gpi_set_timeout(timeout);
-       wdt_gpi_start();
-
-       printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n",
-               wdt_gpi_name, timeout);
-       return nonseekable_open(inode, file);
-}
-
-static int wdt_gpi_release(struct inode *inode, struct file *file)
-{
-       if (nowayout) {
-               printk(KERN_INFO "%s: no way out - watchdog left running\n",
-                       wdt_gpi_name);
-               __module_get(THIS_MODULE);
-               locked = 1;
-       } else {
-               if (expect_close) {
-                       wdt_gpi_stop();
-                       free_irq(wd_irq, &miscdev);
-                       printk(KERN_INFO "%s: watchdog stopped\n",
-                                                       wdt_gpi_name);
-               } else {
-                       printk(KERN_CRIT "%s: unexpected close() -"
-                               " watchdog left running\n",
-                               wdt_gpi_name);
-                       wdt_gpi_set_timeout(timeout);
-                       __module_get(THIS_MODULE);
-                       locked = 1;
-               }
-       }
-
-       atomic_inc(&opencnt);
-       return 0;
-}
-
-static ssize_t wdt_gpi_write(struct file *f, const char __user *d, size_t s,
-                                                               loff_t *o)
-{
-       char val;
-
-       wdt_gpi_set_timeout(timeout);
-       expect_close = (s > 0) && !get_user(val, d) && (val == 'V');
-       return s ? 1 : 0;
-}
-
-static long wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-       long res = -ENOTTY;
-       const long size = _IOC_SIZE(cmd);
-       int stat;
-       void __user *argp = (void __user *)arg;
-       static struct watchdog_info wdinfo = {
-               .identity               = "RM9xxx/GPI watchdog",
-               .firmware_version       = 0,
-               .options                = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
-       };
-
-       if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE))
-               return -ENOTTY;
-
-       if ((_IOC_DIR(cmd) & _IOC_READ)
-           && !access_ok(VERIFY_WRITE, arg, size))
-               return -EFAULT;
-
-       if ((_IOC_DIR(cmd) & _IOC_WRITE)
-           && !access_ok(VERIFY_READ, arg, size))
-               return -EFAULT;
-
-       expect_close = 0;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               wdinfo.options = nowayout ?
-                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
-                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-                       WDIOF_MAGICCLOSE;
-               res = __copy_to_user(argp, &wdinfo, size) ?  -EFAULT : size;
-               break;
-
-       case WDIOC_GETSTATUS:
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               stat = (*(volatile char *) flagaddr & 0x01)
-                       ? WDIOF_CARDRESET : 0;
-               res = __copy_to_user(argp, &stat, size) ?
-                       -EFAULT : size;
-               break;
-
-       case WDIOC_SETOPTIONS:
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_gpi_set_timeout(timeout);
-               res = size;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               {
-                       int val;
-                       if (unlikely(__copy_from_user(&val, argp, size))) {
-                               res = -EFAULT;
-                               break;
-                       }
-
-                       if (val > MAX_TIMEOUT_SECONDS)
-                               val = MAX_TIMEOUT_SECONDS;
-                       timeout = val;
-                       wdt_gpi_set_timeout(val);
-                       res = size;
-                       printk(KERN_INFO "%s: timeout set to %u seconds\n",
-                               wdt_gpi_name, timeout);
-               }
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               res = __copy_to_user(argp, &timeout, size) ?
-                       -EFAULT : size;
-               break;
-       }
-
-       return res;
-}
-
-
-/* Shutdown notifier */
-static int wdt_gpi_notify(struct notifier_block *this, unsigned long code,
-                         void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               wdt_gpi_stop();
-
-       return NOTIFY_DONE;
-}
-
-
-/* Init & exit procedures */
-static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv,
-                                       const char *name, unsigned int type)
-{
-       char buf[80];
-       if (snprintf(buf, sizeof(buf), "%s_0", name) >= sizeof(buf))
-               return NULL;
-       return platform_get_resource_byname(pdv, type, buf);
-}
-
-/* No hotplugging on the platform bus - use __devinit */
-static int __devinit wdt_gpi_probe(struct platform_device *pdv)
-{
-       int res;
-       const struct resource
-               * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
-                                                 IORESOURCE_MEM),
-               * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ,
-                                                 IORESOURCE_IRQ),
-               * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER,
-                                                 0);
-
-       if (unlikely(!rr || !ri || !rc))
-               return -ENXIO;
-
-       wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start);
-       if (unlikely(!wd_regs))
-               return -ENOMEM;
-       wd_irq = ri->start;
-       wd_ctr = rc->start;
-       res = misc_register(&miscdev);
-       if (res)
-               iounmap(wd_regs);
-       else
-               register_reboot_notifier(&wdt_gpi_shutdown);
-       return res;
-}
-
-static int __devexit wdt_gpi_remove(struct platform_device *dev)
-{
-       int res;
-
-       unregister_reboot_notifier(&wdt_gpi_shutdown);
-       res = misc_deregister(&miscdev);
-       iounmap(wd_regs);
-       wd_regs = NULL;
-       return res;
-}
-
-
-/* Device driver init & exit */
-static struct platform_driver wgt_gpi_driver = {
-       .driver = {
-               .name           = wdt_gpi_name,
-               .owner          = THIS_MODULE,
-       },
-       .probe          = wdt_gpi_probe,
-       .remove         = __devexit_p(wdt_gpi_remove),
-};
-
-static int __init wdt_gpi_init_module(void)
-{
-       atomic_set(&opencnt, 1);
-       if (timeout > MAX_TIMEOUT_SECONDS)
-               timeout = MAX_TIMEOUT_SECONDS;
-       return platform_driver_register(&wdt_gpi_driver);
-}
-
-static void __exit wdt_gpi_cleanup_module(void)
-{
-       platform_driver_unregister(&wdt_gpi_driver);
-}
-
-module_init(wdt_gpi_init_module);
-module_exit(wdt_gpi_cleanup_module);
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
index f8fccaa..64d44ef 100644 (file)
@@ -6,10 +6,6 @@ menu "File systems"
 
 if BLOCK
 
-config FS_JOURNAL_INFO
-       bool
-       default n
-
 source "fs/ext2/Kconfig"
 source "fs/ext3/Kconfig"
 source "fs/ext4/Kconfig"
index 94f5110..2c99459 100644 (file)
@@ -35,14 +35,13 @@ static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
                             mnt);
 }
 
-static int anon_inodefs_delete_dentry(struct dentry *dentry)
+/*
+ * anon_inodefs_dname() is called from d_path().
+ */
+static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
 {
-       /*
-        * We faked vfs to believe the dentry was hashed when we created it.
-        * Now we restore the flag so that dput() will work correctly.
-        */
-       dentry->d_flags |= DCACHE_UNHASHED;
-       return 1;
+       return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
+                               dentry->d_name.name);
 }
 
 static struct file_system_type anon_inode_fs_type = {
@@ -51,7 +50,7 @@ static struct file_system_type anon_inode_fs_type = {
        .kill_sb        = kill_anon_super,
 };
 static const struct dentry_operations anon_inodefs_dentry_operations = {
-       .d_delete       = anon_inodefs_delete_dentry,
+       .d_dname        = anon_inodefs_dname,
 };
 
 /*
@@ -119,8 +118,6 @@ struct file *anon_inode_getfile(const char *name,
        atomic_inc(&anon_inode_inode->i_count);
 
        path.dentry->d_op = &anon_inodefs_dentry_operations;
-       /* Do not publish this dentry inside the global dentry hash table */
-       path.dentry->d_flags &= ~DCACHE_UNHASHED;
        d_instantiate(path.dentry, anon_inode_inode);
 
        error = -ENFILE;
index b639dcf..346b694 100644 (file)
@@ -32,7 +32,7 @@
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int aout_core_dump(struct coredump_params *cprm);
 
 static struct linux_binfmt aout_format = {
        .module         = THIS_MODULE,
@@ -89,8 +89,9 @@ if (file->f_op->llseek) { \
  * dumping of the process results in another error..
  */
 
-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int aout_core_dump(struct coredump_params *cprm)
 {
+       struct file *file = cprm->file;
        mm_segment_t fs;
        int has_dumped = 0;
        unsigned long dump_start, dump_size;
@@ -108,16 +109,16 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, u
        current->flags |= PF_DUMPCORE;
                strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
        dump.u_ar0 = offsetof(struct user, regs);
-       dump.signal = signr;
-       aout_dump_thread(regs, &dump);
+       dump.signal = cprm->signr;
+       aout_dump_thread(cprm->regs, &dump);
 
 /* If the size of the dump file exceeds the rlimit, then see what would happen
    if we wrote the stack, but not the data area.  */
-       if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
+       if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > cprm->limit)
                dump.u_dsize = 0;
 
 /* Make sure we have enough room to write the stack and data areas. */
-       if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
+       if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
                dump.u_ssize = 0;
 
 /* make sure we actually have a data and stack area to dump */
index 97b6e9e..edd90c4 100644 (file)
@@ -45,7 +45,7 @@ static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
  * don't even try.
  */
 #ifdef CONFIG_ELF_CORE
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int elf_core_dump(struct coredump_params *cprm);
 #else
 #define elf_core_dump  NULL
 #endif
@@ -1272,8 +1272,9 @@ static int writenote(struct memelfnote *men, struct file *file,
 }
 #undef DUMP_WRITE
 
-#define DUMP_WRITE(addr, nr)   \
-       if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)                           \
+       if ((size += (nr)) > cprm->limit ||             \
+           !dump_write(cprm->file, (addr), (nr)))      \
                goto end_coredump;
 
 static void fill_elf_header(struct elfhdr *elf, int segs,
@@ -1901,7 +1902,7 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
  * and then they are actually written out.  If we run out of core limit
  * we just truncate.
  */
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int elf_core_dump(struct coredump_params *cprm)
 {
        int has_dumped = 0;
        mm_segment_t fs;
@@ -1947,7 +1948,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
         * notes.  This also sets up the file header.
         */
        if (!fill_note_info(elf, segs + 1, /* including notes section */
-                           &info, signr, regs))
+                           &info, cprm->signr, cprm->regs))
                goto cleanup;
 
        has_dumped = 1;
@@ -2009,14 +2010,14 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
 #endif
 
        /* write out the notes section */
-       if (!write_note_info(&info, file, &foffset))
+       if (!write_note_info(&info, cprm->file, &foffset))
                goto end_coredump;
 
-       if (elf_coredump_extra_notes_write(file, &foffset))
+       if (elf_coredump_extra_notes_write(cprm->file, &foffset))
                goto end_coredump;
 
        /* Align to page */
-       if (!dump_seek(file, dataoff - foffset))
+       if (!dump_seek(cprm->file, dataoff - foffset))
                goto end_coredump;
 
        for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -2033,12 +2034,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
                        page = get_dump_page(addr);
                        if (page) {
                                void *kaddr = kmap(page);
-                               stop = ((size += PAGE_SIZE) > limit) ||
-                                       !dump_write(file, kaddr, PAGE_SIZE);
+                               stop = ((size += PAGE_SIZE) > cprm->limit) ||
+                                       !dump_write(cprm->file, kaddr,
+                                                   PAGE_SIZE);
                                kunmap(page);
                                page_cache_release(page);
                        } else
-                               stop = !dump_seek(file, PAGE_SIZE);
+                               stop = !dump_seek(cprm->file, PAGE_SIZE);
                        if (stop)
                                goto end_coredump;
                }
index 7b05538..c25256a 100644 (file)
@@ -76,7 +76,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
                                             struct file *, struct mm_struct *);
 
 #ifdef CONFIG_ELF_CORE
-static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit);
+static int elf_fdpic_core_dump(struct coredump_params *cprm);
 #endif
 
 static struct linux_binfmt elf_fdpic_format = {
@@ -1326,8 +1326,9 @@ static int writenote(struct memelfnote *men, struct file *file)
 #undef DUMP_WRITE
 #undef DUMP_SEEK
 
-#define DUMP_WRITE(addr, nr)   \
-       if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)                           \
+       if ((size += (nr)) > cprm->limit ||             \
+           !dump_write(cprm->file, (addr), (nr)))      \
                goto end_coredump;
 
 static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
@@ -1582,8 +1583,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
  * and then they are actually written out.  If we run out of core limit
  * we just truncate.
  */
-static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
-                              struct file *file, unsigned long limit)
+static int elf_fdpic_core_dump(struct coredump_params *cprm)
 {
 #define        NUM_NOTES       6
        int has_dumped = 0;
@@ -1642,7 +1642,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
                goto cleanup;
 #endif
 
-       if (signr) {
+       if (cprm->signr) {
                struct core_thread *ct;
                struct elf_thread_status *tmp;
 
@@ -1661,14 +1661,14 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
                        int sz;
 
                        tmp = list_entry(t, struct elf_thread_status, list);
-                       sz = elf_dump_thread_status(signr, tmp);
+                       sz = elf_dump_thread_status(cprm->signr, tmp);
                        thread_status_size += sz;
                }
        }
 
        /* now collect the dump for the current */
-       fill_prstatus(prstatus, current, signr);
-       elf_core_copy_regs(&prstatus->pr_reg, regs);
+       fill_prstatus(prstatus, current, cprm->signr);
+       elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
 
        segs = current->mm->map_count;
 #ifdef ELF_CORE_EXTRA_PHDRS
@@ -1703,7 +1703,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
 
        /* Try to dump the FPU. */
        if ((prstatus->pr_fpvalid =
-            elf_core_copy_task_fpregs(current, regs, fpu)))
+            elf_core_copy_task_fpregs(current, cprm->regs, fpu)))
                fill_note(notes + numnote++,
                          "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 #ifdef ELF_CORE_COPY_XFPREGS
@@ -1774,7 +1774,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
 
        /* write out the notes section */
        for (i = 0; i < numnote; i++)
-               if (!writenote(notes + i, file))
+               if (!writenote(notes + i, cprm->file))
                        goto end_coredump;
 
        /* write out the thread status notes section */
@@ -1783,14 +1783,15 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
                                list_entry(t, struct elf_thread_status, list);
 
                for (i = 0; i < tmp->num_notes; i++)
-                       if (!writenote(&tmp->notes[i], file))
+                       if (!writenote(&tmp->notes[i], cprm->file))
                                goto end_coredump;
        }
 
-       if (!dump_seek(file, dataoff))
+       if (!dump_seek(cprm->file, dataoff))
                goto end_coredump;
 
-       if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0)
+       if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
+                                   mm_flags) < 0)
                goto end_coredump;
 
 #ifdef ELF_CORE_WRITE_EXTRA_DATA
index a279665..d4a00ea 100644 (file)
@@ -87,7 +87,7 @@ static int load_flat_shared_library(int id, struct lib_info *p);
 #endif
 
 static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int flat_core_dump(struct coredump_params *cprm);
 
 static struct linux_binfmt flat_format = {
        .module         = THIS_MODULE,
@@ -102,10 +102,10 @@ static struct linux_binfmt flat_format = {
  * Currently only a stub-function.
  */
 
-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int flat_core_dump(struct coredump_params *cprm)
 {
        printk("Process %s:%d received signr %d and should have core dumped\n",
-                       current->comm, current->pid, (int) signr);
+                       current->comm, current->pid, (int) cprm->signr);
        return(1);
 }
 
index eff74b9..2a9b533 100644 (file)
@@ -43,7 +43,7 @@ static int load_som_library(struct file *);
  * don't even try.
  */
 #if 0
-static int som_core_dump(long signr, struct pt_regs *regs, unsigned long limit);
+static int som_core_dump(struct coredump_params *cprm);
 #else
 #define som_core_dump  NULL
 #endif
index 402afe0..7bb3c02 100644 (file)
@@ -4,7 +4,6 @@ config BTRFS_FS
        select LIBCRC32C
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
-       select FS_JOURNAL_INFO
        help
          Btrfs is a new filesystem with extents, writable snapshotting,
          support for multiple devices and many more features.
index 52cbe47..2e9e699 100644 (file)
@@ -94,7 +94,8 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
 /*
  * Needs to be called with fs_mutex held
  */
-static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+static int btrfs_set_acl(struct btrfs_trans_handle *trans,
+                        struct inode *inode, struct posix_acl *acl, int type)
 {
        int ret, size = 0;
        const char *name;
@@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                        goto out;
        }
 
-       ret = __btrfs_setxattr(inode, name, value, size, 0);
-
+       ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
 out:
        kfree(value);
 
@@ -154,7 +154,7 @@ out:
 static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags, int type)
 {
-       int ret = 0;
+       int ret;
        struct posix_acl *acl = NULL;
 
        if (value) {
@@ -167,7 +167,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
                }
        }
 
-       ret = btrfs_set_acl(dentry->d_inode, acl, type);
+       ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type);
 
        posix_acl_release(acl);
 
@@ -196,7 +196,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
  * stuff has been fixed to work with that.  If the locking stuff changes, we
  * need to re-evaluate the acl locking stuff.
  */
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                  struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
        int ret = 0;
@@ -221,7 +222,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
                mode_t mode;
 
                if (S_ISDIR(inode->i_mode)) {
-                       ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
+                       ret = btrfs_set_acl(trans, inode, acl,
+                                           ACL_TYPE_DEFAULT);
                        if (ret)
                                goto failed;
                }
@@ -236,7 +238,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
                        inode->i_mode = mode;
                        if (ret > 0) {
                                /* we need an acl */
-                               ret = btrfs_set_acl(inode, clone,
+                               ret = btrfs_set_acl(trans, inode, clone,
                                                    ACL_TYPE_ACCESS);
                        }
                }
@@ -269,7 +271,7 @@ int btrfs_acl_chmod(struct inode *inode)
 
        ret = posix_acl_chmod_masq(clone, inode->i_mode);
        if (!ret)
-               ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);
+               ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
 
        posix_acl_release(clone);
 
@@ -297,7 +299,8 @@ int btrfs_acl_chmod(struct inode *inode)
        return 0;
 }
 
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                  struct inode *inode, struct inode *dir)
 {
        return 0;
 }
index f6783a4..3f1f50d 100644 (file)
@@ -44,9 +44,6 @@ struct btrfs_inode {
         */
        struct extent_io_tree io_failure_tree;
 
-       /* held while inesrting or deleting extents from files */
-       struct mutex extent_mutex;
-
        /* held while logging the inode in tree-log.c */
        struct mutex log_mutex;
 
@@ -166,7 +163,7 @@ static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
 
 static inline void btrfs_i_size_write(struct inode *inode, u64 size)
 {
-       inode->i_size = size;
+       i_size_write(inode, size);
        BTRFS_I(inode)->disk_i_size = size;
 }
 
index ec96f3a..c4bc570 100644 (file)
@@ -37,6 +37,11 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
                              struct extent_buffer *src_buf);
 static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                   struct btrfs_path *path, int level, int slot);
+static int setup_items_for_insert(struct btrfs_trans_handle *trans,
+                       struct btrfs_root *root, struct btrfs_path *path,
+                       struct btrfs_key *cpu_key, u32 *data_size,
+                       u32 total_data, u32 total_size, int nr);
+
 
 struct btrfs_path *btrfs_alloc_path(void)
 {
@@ -451,9 +456,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                extent_buffer_get(cow);
                spin_unlock(&root->node_lock);
 
-               btrfs_free_extent(trans, root, buf->start, buf->len,
-                                 parent_start, root->root_key.objectid,
-                                 level, 0);
+               btrfs_free_tree_block(trans, root, buf->start, buf->len,
+                               parent_start, root->root_key.objectid, level);
                free_extent_buffer(buf);
                add_root_to_dirty_list(root);
        } else {
@@ -468,9 +472,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                btrfs_set_node_ptr_generation(parent, parent_slot,
                                              trans->transid);
                btrfs_mark_buffer_dirty(parent);
-               btrfs_free_extent(trans, root, buf->start, buf->len,
-                                 parent_start, root->root_key.objectid,
-                                 level, 0);
+               btrfs_free_tree_block(trans, root, buf->start, buf->len,
+                               parent_start, root->root_key.objectid, level);
        }
        if (unlock_orig)
                btrfs_tree_unlock(buf);
@@ -1030,8 +1033,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                btrfs_tree_unlock(mid);
                /* once for the path */
                free_extent_buffer(mid);
-               ret = btrfs_free_extent(trans, root, mid->start, mid->len,
-                                       0, root->root_key.objectid, level, 1);
+               ret = btrfs_free_tree_block(trans, root, mid->start, mid->len,
+                                           0, root->root_key.objectid, level);
                /* once for the root ptr */
                free_extent_buffer(mid);
                return ret;
@@ -1095,10 +1098,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                                       1);
                        if (wret)
                                ret = wret;
-                       wret = btrfs_free_extent(trans, root, bytenr,
-                                                blocksize, 0,
-                                                root->root_key.objectid,
-                                                level, 0);
+                       wret = btrfs_free_tree_block(trans, root,
+                                                    bytenr, blocksize, 0,
+                                                    root->root_key.objectid,
+                                                    level);
                        if (wret)
                                ret = wret;
                } else {
@@ -1143,9 +1146,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                wret = del_ptr(trans, root, path, level + 1, pslot);
                if (wret)
                        ret = wret;
-               wret = btrfs_free_extent(trans, root, bytenr, blocksize,
-                                        0, root->root_key.objectid,
-                                        level, 0);
+               wret = btrfs_free_tree_block(trans, root, bytenr, blocksize,
+                                        0, root->root_key.objectid, level);
                if (wret)
                        ret = wret;
        } else {
@@ -2997,75 +2999,85 @@ again:
        return ret;
 }
 
-/*
- * This function splits a single item into two items,
- * giving 'new_key' to the new item and splitting the
- * old one at split_offset (from the start of the item).
- *
- * The path may be released by this operation.  After
- * the split, the path is pointing to the old item.  The
- * new item is going to be in the same node as the old one.
- *
- * Note, the item being split must be smaller enough to live alone on
- * a tree block with room for one extra struct btrfs_item
- *
- * This allows us to split the item in place, keeping a lock on the
- * leaf the entire time.
- */
-int btrfs_split_item(struct btrfs_trans_handle *trans,
-                    struct btrfs_root *root,
-                    struct btrfs_path *path,
-                    struct btrfs_key *new_key,
-                    unsigned long split_offset)
+static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
+                                        struct btrfs_root *root,
+                                        struct btrfs_path *path, int ins_len)
 {
-       u32 item_size;
+       struct btrfs_key key;
        struct extent_buffer *leaf;
-       struct btrfs_key orig_key;
-       struct btrfs_item *item;
-       struct btrfs_item *new_item;
-       int ret = 0;
-       int slot;
-       u32 nritems;
-       u32 orig_offset;
-       struct btrfs_disk_key disk_key;
-       char *buf;
+       struct btrfs_file_extent_item *fi;
+       u64 extent_len = 0;
+       u32 item_size;
+       int ret;
 
        leaf = path->nodes[0];
-       btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
-       if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item))
-               goto split;
+       btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+
+       BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY &&
+              key.type != BTRFS_EXTENT_CSUM_KEY);
+
+       if (btrfs_leaf_free_space(root, leaf) >= ins_len)
+               return 0;
 
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+       if (key.type == BTRFS_EXTENT_DATA_KEY) {
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               extent_len = btrfs_file_extent_num_bytes(leaf, fi);
+       }
        btrfs_release_path(root, path);
 
-       path->search_for_split = 1;
        path->keep_locks = 1;
-
-       ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1);
+       path->search_for_split = 1;
+       ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
        path->search_for_split = 0;
+       if (ret < 0)
+               goto err;
 
+       ret = -EAGAIN;
+       leaf = path->nodes[0];
        /* if our item isn't there or got smaller, return now */
-       if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0],
-                                                       path->slots[0])) {
-               path->keep_locks = 0;
-               return -EAGAIN;
+       if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
+               goto err;
+
+       if (key.type == BTRFS_EXTENT_DATA_KEY) {
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               if (extent_len != btrfs_file_extent_num_bytes(leaf, fi))
+                       goto err;
        }
 
        btrfs_set_path_blocking(path);
-       ret = split_leaf(trans, root, &orig_key, path,
-                        sizeof(struct btrfs_item), 1);
-       path->keep_locks = 0;
+       ret = split_leaf(trans, root, &key, path, ins_len, 1);
        BUG_ON(ret);
 
+       path->keep_locks = 0;
        btrfs_unlock_up_safe(path, 1);
+       return 0;
+err:
+       path->keep_locks = 0;
+       return ret;
+}
+
+static noinline int split_item(struct btrfs_trans_handle *trans,
+                              struct btrfs_root *root,
+                              struct btrfs_path *path,
+                              struct btrfs_key *new_key,
+                              unsigned long split_offset)
+{
+       struct extent_buffer *leaf;
+       struct btrfs_item *item;
+       struct btrfs_item *new_item;
+       int slot;
+       char *buf;
+       u32 nritems;
+       u32 item_size;
+       u32 orig_offset;
+       struct btrfs_disk_key disk_key;
+
        leaf = path->nodes[0];
        BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 
-split:
-       /*
-        * make sure any changes to the path from split_leaf leave it
-        * in a blocking state
-        */
        btrfs_set_path_blocking(path);
 
        item = btrfs_item_nr(leaf, path->slots[0]);
@@ -3073,19 +3085,19 @@ split:
        item_size = btrfs_item_size(leaf, item);
 
        buf = kmalloc(item_size, GFP_NOFS);
+       if (!buf)
+               return -ENOMEM;
+
        read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
                            path->slots[0]), item_size);
-       slot = path->slots[0] + 1;
-       leaf = path->nodes[0];
 
+       slot = path->slots[0] + 1;
        nritems = btrfs_header_nritems(leaf);
-
        if (slot != nritems) {
                /* shift the items */
                memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
-                             btrfs_item_nr_offset(slot),
-                             (nritems - slot) * sizeof(struct btrfs_item));
-
+                               btrfs_item_nr_offset(slot),
+                               (nritems - slot) * sizeof(struct btrfs_item));
        }
 
        btrfs_cpu_key_to_disk(&disk_key, new_key);
@@ -3113,16 +3125,81 @@ split:
                            item_size - split_offset);
        btrfs_mark_buffer_dirty(leaf);
 
-       ret = 0;
-       if (btrfs_leaf_free_space(root, leaf) < 0) {
-               btrfs_print_leaf(root, leaf);
-               BUG();
-       }
+       BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
        kfree(buf);
+       return 0;
+}
+
+/*
+ * This function splits a single item into two items,
+ * giving 'new_key' to the new item and splitting the
+ * old one at split_offset (from the start of the item).
+ *
+ * The path may be released by this operation.  After
+ * the split, the path is pointing to the old item.  The
+ * new item is going to be in the same node as the old one.
+ *
+ * Note, the item being split must be smaller enough to live alone on
+ * a tree block with room for one extra struct btrfs_item
+ *
+ * This allows us to split the item in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_split_item(struct btrfs_trans_handle *trans,
+                    struct btrfs_root *root,
+                    struct btrfs_path *path,
+                    struct btrfs_key *new_key,
+                    unsigned long split_offset)
+{
+       int ret;
+       ret = setup_leaf_for_split(trans, root, path,
+                                  sizeof(struct btrfs_item));
+       if (ret)
+               return ret;
+
+       ret = split_item(trans, root, path, new_key, split_offset);
        return ret;
 }
 
 /*
+ * This function duplicate a item, giving 'new_key' to the new item.
+ * It guarantees both items live in the same tree leaf and the new item
+ * is contiguous with the original item.
+ *
+ * This allows us to split file extent in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root,
+                        struct btrfs_path *path,
+                        struct btrfs_key *new_key)
+{
+       struct extent_buffer *leaf;
+       int ret;
+       u32 item_size;
+
+       leaf = path->nodes[0];
+       item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+       ret = setup_leaf_for_split(trans, root, path,
+                                  item_size + sizeof(struct btrfs_item));
+       if (ret)
+               return ret;
+
+       path->slots[0]++;
+       ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
+                                    item_size, item_size +
+                                    sizeof(struct btrfs_item), 1);
+       BUG_ON(ret);
+
+       leaf = path->nodes[0];
+       memcpy_extent_buffer(leaf,
+                            btrfs_item_ptr_offset(leaf, path->slots[0]),
+                            btrfs_item_ptr_offset(leaf, path->slots[0] - 1),
+                            item_size);
+       return 0;
+}
+
+/*
  * make the item pointed to by the path smaller.  new_size indicates
  * how small to make it, and from_end tells us if we just chop bytes
  * off the end of the item or if we shift the item to chop bytes off
@@ -3714,8 +3791,8 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
         */
        btrfs_unlock_up_safe(path, 0);
 
-       ret = btrfs_free_extent(trans, root, leaf->start, leaf->len,
-                               0, root->root_key.objectid, 0, 0);
+       ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len,
+                                   0, root->root_key.objectid, 0);
        return ret;
 }
 /*
index 444b3e9..9f806dd 100644 (file)
@@ -310,6 +310,9 @@ struct btrfs_header {
 #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
                                        sizeof(struct btrfs_item) - \
                                        sizeof(struct btrfs_file_extent_item))
+#define BTRFS_MAX_XATTR_SIZE(r)        (BTRFS_LEAF_DATA_SIZE(r) - \
+                                sizeof(struct btrfs_item) -\
+                                sizeof(struct btrfs_dir_item))
 
 
 /*
@@ -859,8 +862,9 @@ struct btrfs_fs_info {
        struct mutex ordered_operations_mutex;
        struct rw_semaphore extent_commit_sem;
 
-       struct rw_semaphore subvol_sem;
+       struct rw_semaphore cleanup_work_sem;
 
+       struct rw_semaphore subvol_sem;
        struct srcu_struct subvol_srcu;
 
        struct list_head trans_list;
@@ -868,6 +872,9 @@ struct btrfs_fs_info {
        struct list_head dead_roots;
        struct list_head caching_block_groups;
 
+       spinlock_t delayed_iput_lock;
+       struct list_head delayed_iputs;
+
        atomic_t nr_async_submits;
        atomic_t async_submit_draining;
        atomic_t nr_async_bios;
@@ -1034,12 +1041,12 @@ struct btrfs_root {
        int ref_cows;
        int track_dirty;
        int in_radix;
+       int clean_orphans;
 
        u64 defrag_trans_start;
        struct btrfs_key defrag_progress;
        struct btrfs_key defrag_max;
        int defrag_running;
-       int defrag_level;
        char *name;
        int in_sysfs;
 
@@ -1975,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                                        u64 parent, u64 root_objectid,
                                        struct btrfs_disk_key *key, int level,
                                        u64 hint, u64 empty_size);
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         u64 bytenr, u32 blocksize,
+                         u64 parent, u64 root_objectid, int level);
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
                                            struct btrfs_root *root,
                                            u64 bytenr, u32 blocksize,
@@ -2089,6 +2100,10 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
                     struct btrfs_path *path,
                     struct btrfs_key *new_key,
                     unsigned long split_offset);
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root,
+                        struct btrfs_path *path,
+                        struct btrfs_key *new_key);
 int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
                      *root, struct btrfs_key *key, struct btrfs_path *p, int
                      ins_len, int cow);
@@ -2196,9 +2211,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
                              struct btrfs_path *path,
                              struct btrfs_dir_item *di);
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-                           struct btrfs_root *root, const char *name,
-                           u16 name_len, const void *data, u16 data_len,
-                           u64 dir);
+                           struct btrfs_root *root,
+                           struct btrfs_path *path, u64 objectid,
+                           const char *name, u16 name_len,
+                           const void *data, u16 data_len);
 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
                                          struct btrfs_root *root,
                                          struct btrfs_path *path, u64 dir,
@@ -2292,7 +2308,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
                               struct inode *inode, u64 new_size,
                               u32 min_type);
 
-int btrfs_start_delalloc_inodes(struct btrfs_root *root);
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
 int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
 int btrfs_writepages(struct address_space *mapping,
                     struct writeback_control *wbc);
@@ -2332,6 +2348,8 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
 int btrfs_invalidate_inodes(struct btrfs_root *root);
+void btrfs_add_delayed_iput(struct inode *inode);
+void btrfs_run_delayed_iputs(struct btrfs_root *root);
 extern const struct dentry_operations btrfs_dentry_operations;
 
 /* ioctl.c */
@@ -2345,12 +2363,9 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                            int skip_pinned);
 int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 extern const struct file_operations btrfs_file_operations;
-int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                      struct btrfs_root *root, struct inode *inode,
-                      u64 start, u64 end, u64 locked_end,
-                      u64 inline_limit, u64 *hint_block, int drop_cache);
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+                      u64 start, u64 end, u64 *hint_byte, int drop_cache);
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-                             struct btrfs_root *root,
                              struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
 
@@ -2380,7 +2395,8 @@ int btrfs_check_acl(struct inode *inode, int mask);
 #else
 #define btrfs_check_acl NULL
 #endif
-int btrfs_init_acl(struct inode *inode, struct inode *dir);
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                  struct inode *inode, struct inode *dir);
 int btrfs_acl_chmod(struct inode *inode);
 
 /* relocation.c */
index f3a6075..e9103b3 100644 (file)
@@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
  * into the tree
  */
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-                           struct btrfs_root *root, const char *name,
-                           u16 name_len, const void *data, u16 data_len,
-                           u64 dir)
+                           struct btrfs_root *root,
+                           struct btrfs_path *path, u64 objectid,
+                           const char *name, u16 name_len,
+                           const void *data, u16 data_len)
 {
        int ret = 0;
-       struct btrfs_path *path;
        struct btrfs_dir_item *dir_item;
        unsigned long name_ptr, data_ptr;
        struct btrfs_key key, location;
@@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
        u32 data_size;
 
-       key.objectid = dir;
+       BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
+
+       key.objectid = objectid;
        btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
        key.offset = btrfs_name_hash(name, name_len);
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-       if (name_len + data_len + sizeof(struct btrfs_dir_item) >
-           BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item))
-               return -ENOSPC;
 
        data_size = sizeof(*dir_item) + name_len + data_len;
        dir_item = insert_with_overflow(trans, root, path, &key, data_size,
@@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
        write_extent_buffer(leaf, data, data_ptr, data_len);
        btrfs_mark_buffer_dirty(path->nodes[0]);
 
-       btrfs_free_path(path);
        return ret;
 }
 
index 02b6afb..009e3bd 100644 (file)
@@ -892,6 +892,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->stripesize = stripesize;
        root->ref_cows = 0;
        root->track_dirty = 0;
+       root->in_radix = 0;
+       root->clean_orphans = 0;
 
        root->fs_info = fs_info;
        root->objectid = objectid;
@@ -928,7 +930,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->defrag_trans_start = fs_info->generation;
        init_completion(&root->kobj_unregister);
        root->defrag_running = 0;
-       root->defrag_level = 0;
        root->root_key.objectid = objectid;
        root->anon_super.s_root = NULL;
        root->anon_super.s_dev = 0;
@@ -980,12 +981,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 
        while (1) {
                ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
-                                   0, &start, &end, EXTENT_DIRTY);
+                               0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
                if (ret)
                        break;
 
-               clear_extent_dirty(&log_root_tree->dirty_log_pages,
-                                  start, end, GFP_NOFS);
+               clear_extent_bits(&log_root_tree->dirty_log_pages, start, end,
+                                 EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
        }
        eb = fs_info->log_root_tree->node;
 
@@ -1210,8 +1211,10 @@ again:
        ret = radix_tree_insert(&fs_info->fs_roots_radix,
                                (unsigned long)root->root_key.objectid,
                                root);
-       if (ret == 0)
+       if (ret == 0) {
                root->in_radix = 1;
+               root->clean_orphans = 1;
+       }
        spin_unlock(&fs_info->fs_roots_radix_lock);
        radix_tree_preload_end();
        if (ret) {
@@ -1225,10 +1228,6 @@ again:
        ret = btrfs_find_dead_roots(fs_info->tree_root,
                                    root->root_key.objectid);
        WARN_ON(ret);
-
-       if (!(fs_info->sb->s_flags & MS_RDONLY))
-               btrfs_orphan_cleanup(root);
-
        return root;
 fail:
        free_fs_root(root);
@@ -1477,6 +1476,7 @@ static int cleaner_kthread(void *arg)
 
                if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
                    mutex_trylock(&root->fs_info->cleaner_mutex)) {
+                       btrfs_run_delayed_iputs(root);
                        btrfs_clean_old_snapshots(root);
                        mutex_unlock(&root->fs_info->cleaner_mutex);
                }
@@ -1606,6 +1606,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
        INIT_LIST_HEAD(&fs_info->trans_list);
        INIT_LIST_HEAD(&fs_info->dead_roots);
+       INIT_LIST_HEAD(&fs_info->delayed_iputs);
        INIT_LIST_HEAD(&fs_info->hashers);
        INIT_LIST_HEAD(&fs_info->delalloc_inodes);
        INIT_LIST_HEAD(&fs_info->ordered_operations);
@@ -1614,6 +1615,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        spin_lock_init(&fs_info->new_trans_lock);
        spin_lock_init(&fs_info->ref_cache_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
+       spin_lock_init(&fs_info->delayed_iput_lock);
 
        init_completion(&fs_info->kobj_unregister);
        fs_info->tree_root = tree_root;
@@ -1689,6 +1691,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->cleaner_mutex);
        mutex_init(&fs_info->volume_mutex);
        init_rwsem(&fs_info->extent_commit_sem);
+       init_rwsem(&fs_info->cleanup_work_sem);
        init_rwsem(&fs_info->subvol_sem);
 
        btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
@@ -2386,8 +2389,14 @@ int btrfs_commit_super(struct btrfs_root *root)
        int ret;
 
        mutex_lock(&root->fs_info->cleaner_mutex);
+       btrfs_run_delayed_iputs(root);
        btrfs_clean_old_snapshots(root);
        mutex_unlock(&root->fs_info->cleaner_mutex);
+
+       /* wait until ongoing cleanup work done */
+       down_write(&root->fs_info->cleanup_work_sem);
+       up_write(&root->fs_info->cleanup_work_sem);
+
        trans = btrfs_start_transaction(root, 1);
        ret = btrfs_commit_transaction(trans, root);
        BUG_ON(ret);
index 94627c4..56e5013 100644 (file)
@@ -195,6 +195,14 @@ static int exclude_super_stripes(struct btrfs_root *root,
        int stripe_len;
        int i, nr, ret;
 
+       if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) {
+               stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid;
+               cache->bytes_super += stripe_len;
+               ret = add_excluded_extent(root, cache->key.objectid,
+                                         stripe_len);
+               BUG_ON(ret);
+       }
+
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                bytenr = btrfs_sb_offset(i);
                ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
@@ -255,7 +263,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
                if (ret)
                        break;
 
-               if (extent_start == start) {
+               if (extent_start <= start) {
                        start = extent_end + 1;
                } else if (extent_start > start && extent_start < end) {
                        size = extent_start - start;
@@ -2880,9 +2888,9 @@ static noinline void flush_delalloc_async(struct btrfs_work *work)
        root = async->root;
        info = async->info;
 
-       btrfs_start_delalloc_inodes(root);
+       btrfs_start_delalloc_inodes(root, 0);
        wake_up(&info->flush_wait);
-       btrfs_wait_ordered_extents(root, 0);
+       btrfs_wait_ordered_extents(root, 0, 0);
 
        spin_lock(&info->lock);
        info->flushing = 0;
@@ -2956,8 +2964,8 @@ static void flush_delalloc(struct btrfs_root *root,
        return;
 
 flush:
-       btrfs_start_delalloc_inodes(root);
-       btrfs_wait_ordered_extents(root, 0);
+       btrfs_start_delalloc_inodes(root, 0);
+       btrfs_wait_ordered_extents(root, 0, 0);
 
        spin_lock(&info->lock);
        info->flushing = 0;
@@ -3454,14 +3462,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
        else
                old_val -= num_bytes;
        btrfs_set_super_bytes_used(&info->super_copy, old_val);
-
-       /* block accounting for root item */
-       old_val = btrfs_root_used(&root->root_item);
-       if (alloc)
-               old_val += num_bytes;
-       else
-               old_val -= num_bytes;
-       btrfs_set_root_used(&root->root_item, old_val);
        spin_unlock(&info->delalloc_lock);
 
        while (total) {
@@ -4049,6 +4049,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         u64 bytenr, u32 blocksize,
+                         u64 parent, u64 root_objectid, int level)
+{
+       u64 used;
+       spin_lock(&root->node_lock);
+       used = btrfs_root_used(&root->root_item) - blocksize;
+       btrfs_set_root_used(&root->root_item, used);
+       spin_unlock(&root->node_lock);
+
+       return btrfs_free_extent(trans, root, bytenr, blocksize,
+                                parent, root_objectid, level, 0);
+}
+
 static u64 stripe_align(struct btrfs_root *root, u64 val)
 {
        u64 mask = ((u64)root->stripesize - 1);
@@ -4578,7 +4593,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 {
        int ret;
        u64 search_start = 0;
-       struct btrfs_fs_info *info = root->fs_info;
 
        data = btrfs_get_alloc_profile(root, data);
 again:
@@ -4586,17 +4600,9 @@ again:
         * the only place that sets empty_size is btrfs_realloc_node, which
         * is not called recursively on allocations
         */
-       if (empty_size || root->ref_cows) {
-               if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
-                       ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                    2 * 1024 * 1024,
-                                    BTRFS_BLOCK_GROUP_METADATA |
-                                    (info->metadata_alloc_profile &
-                                     info->avail_metadata_alloc_bits), 0);
-               }
+       if (empty_size || root->ref_cows)
                ret = do_chunk_alloc(trans, root->fs_info->extent_root,
                                     num_bytes + 2 * 1024 * 1024, data, 0);
-       }
 
        WARN_ON(num_bytes < root->sectorsize);
        ret = find_free_extent(trans, root, num_bytes, empty_size,
@@ -4897,6 +4903,14 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans,
                                        extent_op);
                BUG_ON(ret);
        }
+
+       if (root_objectid == root->root_key.objectid) {
+               u64 used;
+               spin_lock(&root->node_lock);
+               used = btrfs_root_used(&root->root_item) + num_bytes;
+               btrfs_set_root_used(&root->root_item, used);
+               spin_unlock(&root->node_lock);
+       }
        return ret;
 }
 
@@ -4919,8 +4933,16 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
        btrfs_set_buffer_uptodate(buf);
 
        if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
-               set_extent_dirty(&root->dirty_log_pages, buf->start,
-                        buf->start + buf->len - 1, GFP_NOFS);
+               /*
+                * we allow two log transactions at a time, use different
+                * EXENT bit to differentiate dirty pages.
+                */
+               if (root->log_transid % 2 == 0)
+                       set_extent_dirty(&root->dirty_log_pages, buf->start,
+                                       buf->start + buf->len - 1, GFP_NOFS);
+               else
+                       set_extent_new(&root->dirty_log_pages, buf->start,
+                                       buf->start + buf->len - 1, GFP_NOFS);
        } else {
                set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
                         buf->start + buf->len - 1, GFP_NOFS);
index 77f7593..feaa13b 100644 (file)
@@ -179,18 +179,14 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                }
                flags = em->flags;
                if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
-                       if (em->start <= start &&
-                           (!testend || em->start + em->len >= start + len)) {
+                       if (testend && em->start + em->len >= start + len) {
                                free_extent_map(em);
                                write_unlock(&em_tree->lock);
                                break;
                        }
-                       if (start < em->start) {
-                               len = em->start - start;
-                       } else {
+                       start = em->start + em->len;
+                       if (testend)
                                len = start + len - (em->start + em->len);
-                               start = em->start + em->len;
-                       }
                        free_extent_map(em);
                        write_unlock(&em_tree->lock);
                        continue;
@@ -265,319 +261,247 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
  * If an extent intersects the range but is not entirely inside the range
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
- *
- * inline_limit is used to tell this code which offsets in the file to keep
- * if they contain inline extents.
  */
-noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                      struct btrfs_root *root, struct inode *inode,
-                      u64 start, u64 end, u64 locked_end,
-                      u64 inline_limit, u64 *hint_byte, int drop_cache)
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+                      u64 start, u64 end, u64 *hint_byte, int drop_cache)
 {
-       u64 extent_end = 0;
-       u64 search_start = start;
-       u64 ram_bytes = 0;
-       u64 disk_bytenr = 0;
-       u64 orig_locked_end = locked_end;
-       u8 compression;
-       u8 encryption;
-       u16 other_encoding = 0;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_buffer *leaf;
-       struct btrfs_file_extent_item *extent;
+       struct btrfs_file_extent_item *fi;
        struct btrfs_path *path;
        struct btrfs_key key;
-       struct btrfs_file_extent_item old;
-       int keep;
-       int slot;
-       int bookend;
-       int found_type = 0;
-       int found_extent;
-       int found_inline;
+       struct btrfs_key new_key;
+       u64 search_start = start;
+       u64 disk_bytenr = 0;
+       u64 num_bytes = 0;
+       u64 extent_offset = 0;
+       u64 extent_end = 0;
+       int del_nr = 0;
+       int del_slot = 0;
+       int extent_type;
        int recow;
        int ret;
 
-       inline_limit = 0;
        if (drop_cache)
                btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
+
        while (1) {
                recow = 0;
-               btrfs_release_path(root, path);
                ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
                                               search_start, -1);
                if (ret < 0)
-                       goto out;
-               if (ret > 0) {
-                       if (path->slots[0] == 0) {
-                               ret = 0;
-                               goto out;
-                       }
-                       path->slots[0]--;
+                       break;
+               if (ret > 0 && path->slots[0] > 0 && search_start == start) {
+                       leaf = path->nodes[0];
+                       btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
+                       if (key.objectid == inode->i_ino &&
+                           key.type == BTRFS_EXTENT_DATA_KEY)
+                               path->slots[0]--;
                }
+               ret = 0;
 next_slot:
-               keep = 0;
-               bookend = 0;
-               found_extent = 0;
-               found_inline = 0;
-               compression = 0;
-               encryption = 0;
-               extent = NULL;
                leaf = path->nodes[0];
-               slot = path->slots[0];
-               ret = 0;
-               btrfs_item_key_to_cpu(leaf, &key, slot);
-               if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY &&
-                   key.offset >= end) {
-                       goto out;
-               }
-               if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
-                   key.objectid != inode->i_ino) {
-                       goto out;
-               }
-               if (recow) {
-                       search_start = max(key.offset, start);
-                       continue;
-               }
-               if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
-                       extent = btrfs_item_ptr(leaf, slot,
-                                               struct btrfs_file_extent_item);
-                       found_type = btrfs_file_extent_type(leaf, extent);
-                       compression = btrfs_file_extent_compression(leaf,
-                                                                   extent);
-                       encryption = btrfs_file_extent_encryption(leaf,
-                                                                 extent);
-                       other_encoding = btrfs_file_extent_other_encoding(leaf,
-                                                                 extent);
-                       if (found_type == BTRFS_FILE_EXTENT_REG ||
-                           found_type == BTRFS_FILE_EXTENT_PREALLOC) {
-                               extent_end =
-                                    btrfs_file_extent_disk_bytenr(leaf,
-                                                                  extent);
-                               if (extent_end)
-                                       *hint_byte = extent_end;
-
-                               extent_end = key.offset +
-                                    btrfs_file_extent_num_bytes(leaf, extent);
-                               ram_bytes = btrfs_file_extent_ram_bytes(leaf,
-                                                               extent);
-                               found_extent = 1;
-                       } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
-                               found_inline = 1;
-                               extent_end = key.offset +
-                                    btrfs_file_extent_inline_len(leaf, extent);
+               if (path->slots[0] >= btrfs_header_nritems(leaf)) {
+                       BUG_ON(del_nr > 0);
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret < 0)
+                               break;
+                       if (ret > 0) {
+                               ret = 0;
+                               break;
                        }
+                       leaf = path->nodes[0];
+                       recow = 1;
+               }
+
+               btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+               if (key.objectid > inode->i_ino ||
+                   key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+                       break;
+
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+               extent_type = btrfs_file_extent_type(leaf, fi);
+
+               if (extent_type == BTRFS_FILE_EXTENT_REG ||
+                   extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
+                       disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
+                       num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
+                       extent_offset = btrfs_file_extent_offset(leaf, fi);
+                       extent_end = key.offset +
+                               btrfs_file_extent_num_bytes(leaf, fi);
+               } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+                       extent_end = key.offset +
+                               btrfs_file_extent_inline_len(leaf, fi);
                } else {
+                       WARN_ON(1);
                        extent_end = search_start;
                }
 
-               /* we found nothing we can drop */
-               if ((!found_extent && !found_inline) ||
-                   search_start >= extent_end) {
-                       int nextret;
-                       u32 nritems;
-                       nritems = btrfs_header_nritems(leaf);
-                       if (slot >= nritems - 1) {
-                               nextret = btrfs_next_leaf(root, path);
-                               if (nextret)
-                                       goto out;
-                               recow = 1;
-                       } else {
-                               path->slots[0]++;
-                       }
+               if (extent_end <= search_start) {
+                       path->slots[0]++;
                        goto next_slot;
                }
 
-               if (end <= extent_end && start >= key.offset && found_inline)
-                       *hint_byte = EXTENT_MAP_INLINE;
-
-               if (found_extent) {
-                       read_extent_buffer(leaf, &old, (unsigned long)extent,
-                                          sizeof(old));
-               }
-
-               if (end < extent_end && end >= key.offset) {
-                       bookend = 1;
-                       if (found_inline && start <= key.offset)
-                               keep = 1;
+               search_start = max(key.offset, start);
+               if (recow) {
+                       btrfs_release_path(root, path);
+                       continue;
                }
 
-               if (bookend && found_extent) {
-                       if (locked_end < extent_end) {
-                               ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-                                               locked_end, extent_end - 1,
-                                               GFP_NOFS);
-                               if (!ret) {
-                                       btrfs_release_path(root, path);
-                                       lock_extent(&BTRFS_I(inode)->io_tree,
-                                               locked_end, extent_end - 1,
-                                               GFP_NOFS);
-                                       locked_end = extent_end;
-                                       continue;
-                               }
-                               locked_end = extent_end;
+               /*
+                *     | - range to drop - |
+                *  | -------- extent -------- |
+                */
+               if (start > key.offset && end < extent_end) {
+                       BUG_ON(del_nr > 0);
+                       BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+                       memcpy(&new_key, &key, sizeof(new_key));
+                       new_key.offset = start;
+                       ret = btrfs_duplicate_item(trans, root, path,
+                                                  &new_key);
+                       if (ret == -EAGAIN) {
+                               btrfs_release_path(root, path);
+                               continue;
                        }
-                       disk_bytenr = le64_to_cpu(old.disk_bytenr);
-                       if (disk_bytenr != 0) {
+                       if (ret < 0)
+                               break;
+
+                       leaf = path->nodes[0];
+                       fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
+                                           struct btrfs_file_extent_item);
+                       btrfs_set_file_extent_num_bytes(leaf, fi,
+                                                       start - key.offset);
+
+                       fi = btrfs_item_ptr(leaf, path->slots[0],
+                                           struct btrfs_file_extent_item);
+
+                       extent_offset += start - key.offset;
+                       btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+                       btrfs_set_file_extent_num_bytes(leaf, fi,
+                                                       extent_end - start);
+                       btrfs_mark_buffer_dirty(leaf);
+
+                       if (disk_bytenr > 0) {
                                ret = btrfs_inc_extent_ref(trans, root,
-                                          disk_bytenr,
-                                          le64_to_cpu(old.disk_num_bytes), 0,
-                                          root->root_key.objectid,
-                                          key.objectid, key.offset -
-                                          le64_to_cpu(old.offset));
+                                               disk_bytenr, num_bytes, 0,
+                                               root->root_key.objectid,
+                                               new_key.objectid,
+                                               start - extent_offset);
                                BUG_ON(ret);
+                               *hint_byte = disk_bytenr;
                        }
+                       key.offset = start;
                }
+               /*
+                *  | ---- range to drop ----- |
+                *      | -------- extent -------- |
+                */
+               if (start <= key.offset && end < extent_end) {
+                       BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
 
-               if (found_inline) {
-                       u64 mask = root->sectorsize - 1;
-                       search_start = (extent_end + mask) & ~mask;
-               } else
-                       search_start = extent_end;
-
-               /* truncate existing extent */
-               if (start > key.offset) {
-                       u64 new_num;
-                       u64 old_num;
-                       keep = 1;
-                       WARN_ON(start & (root->sectorsize - 1));
-                       if (found_extent) {
-                               new_num = start - key.offset;
-                               old_num = btrfs_file_extent_num_bytes(leaf,
-                                                                     extent);
-                               *hint_byte =
-                                       btrfs_file_extent_disk_bytenr(leaf,
-                                                                     extent);
-                               if (btrfs_file_extent_disk_bytenr(leaf,
-                                                                 extent)) {
-                                       inode_sub_bytes(inode, old_num -
-                                                       new_num);
-                               }
-                               btrfs_set_file_extent_num_bytes(leaf,
-                                                       extent, new_num);
-                               btrfs_mark_buffer_dirty(leaf);
-                       } else if (key.offset < inline_limit &&
-                                  (end > extent_end) &&
-                                  (inline_limit < extent_end)) {
-                               u32 new_size;
-                               new_size = btrfs_file_extent_calc_inline_size(
-                                                  inline_limit - key.offset);
-                               inode_sub_bytes(inode, extent_end -
-                                               inline_limit);
-                               btrfs_set_file_extent_ram_bytes(leaf, extent,
-                                                       new_size);
-                               if (!compression && !encryption) {
-                                       btrfs_truncate_item(trans, root, path,
-                                                           new_size, 1);
-                               }
+                       memcpy(&new_key, &key, sizeof(new_key));
+                       new_key.offset = end;
+                       btrfs_set_item_key_safe(trans, root, path, &new_key);
+
+                       extent_offset += end - key.offset;
+                       btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+                       btrfs_set_file_extent_num_bytes(leaf, fi,
+                                                       extent_end - end);
+                       btrfs_mark_buffer_dirty(leaf);
+                       if (disk_bytenr > 0) {
+                               inode_sub_bytes(inode, end - key.offset);
+                               *hint_byte = disk_bytenr;
                        }
+                       break;
                }
-               /* delete the entire extent */
-               if (!keep) {
-                       if (found_inline)
-                               inode_sub_bytes(inode, extent_end -
-                                               key.offset);
-                       ret = btrfs_del_item(trans, root, path);
-                       /* TODO update progress marker and return */
-                       BUG_ON(ret);
-                       extent = NULL;
-                       btrfs_release_path(root, path);
-                       /* the extent will be freed later */
-               }
-               if (bookend && found_inline && start <= key.offset) {
-                       u32 new_size;
-                       new_size = btrfs_file_extent_calc_inline_size(
-                                                  extent_end - end);
-                       inode_sub_bytes(inode, end - key.offset);
-                       btrfs_set_file_extent_ram_bytes(leaf, extent,
-                                                       new_size);
-                       if (!compression && !encryption)
-                               ret = btrfs_truncate_item(trans, root, path,
-                                                         new_size, 0);
-                       BUG_ON(ret);
-               }
-               /* create bookend, splitting the extent in two */
-               if (bookend && found_extent) {
-                       struct btrfs_key ins;
-                       ins.objectid = inode->i_ino;
-                       ins.offset = end;
-                       btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
 
-                       btrfs_release_path(root, path);
-                       path->leave_spinning = 1;
-                       ret = btrfs_insert_empty_item(trans, root, path, &ins,
-                                                     sizeof(*extent));
-                       BUG_ON(ret);
+               search_start = extent_end;
+               /*
+                *       | ---- range to drop ----- |
+                *  | -------- extent -------- |
+                */
+               if (start > key.offset && end >= extent_end) {
+                       BUG_ON(del_nr > 0);
+                       BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
 
-                       leaf = path->nodes[0];
-                       extent = btrfs_item_ptr(leaf, path->slots[0],
-                                               struct btrfs_file_extent_item);
-                       write_extent_buffer(leaf, &old,
-                                           (unsigned long)extent, sizeof(old));
-
-                       btrfs_set_file_extent_compression(leaf, extent,
-                                                         compression);
-                       btrfs_set_file_extent_encryption(leaf, extent,
-                                                        encryption);
-                       btrfs_set_file_extent_other_encoding(leaf, extent,
-                                                            other_encoding);
-                       btrfs_set_file_extent_offset(leaf, extent,
-                                   le64_to_cpu(old.offset) + end - key.offset);
-                       WARN_ON(le64_to_cpu(old.num_bytes) <
-                               (extent_end - end));
-                       btrfs_set_file_extent_num_bytes(leaf, extent,
-                                                       extent_end - end);
+                       btrfs_set_file_extent_num_bytes(leaf, fi,
+                                                       start - key.offset);
+                       btrfs_mark_buffer_dirty(leaf);
+                       if (disk_bytenr > 0) {
+                               inode_sub_bytes(inode, extent_end - start);
+                               *hint_byte = disk_bytenr;
+                       }
+                       if (end == extent_end)
+                               break;
 
-                       /*
-                        * set the ram bytes to the size of the full extent
-                        * before splitting.  This is a worst case flag,
-                        * but its the best we can do because we don't know
-                        * how splitting affects compression
-                        */
-                       btrfs_set_file_extent_ram_bytes(leaf, extent,
-                                                       ram_bytes);
-                       btrfs_set_file_extent_type(leaf, extent, found_type);
-
-                       btrfs_unlock_up_safe(path, 1);
-                       btrfs_mark_buffer_dirty(path->nodes[0]);
-                       btrfs_set_lock_blocking(path->nodes[0]);
-
-                       path->leave_spinning = 0;
-                       btrfs_release_path(root, path);
-                       if (disk_bytenr != 0)
-                               inode_add_bytes(inode, extent_end - end);
+                       path->slots[0]++;
+                       goto next_slot;
                }
 
-               if (found_extent && !keep) {
-                       u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr);
+               /*
+                *  | ---- range to drop ----- |
+                *    | ------ extent ------ |
+                */
+               if (start <= key.offset && end >= extent_end) {
+                       if (del_nr == 0) {
+                               del_slot = path->slots[0];
+                               del_nr = 1;
+                       } else {
+                               BUG_ON(del_slot + del_nr != path->slots[0]);
+                               del_nr++;
+                       }
 
-                       if (old_disk_bytenr != 0) {
+                       if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                inode_sub_bytes(inode,
-                                               le64_to_cpu(old.num_bytes));
+                                               extent_end - key.offset);
+                               extent_end = ALIGN(extent_end,
+                                                  root->sectorsize);
+                       } else if (disk_bytenr > 0) {
                                ret = btrfs_free_extent(trans, root,
-                                               old_disk_bytenr,
-                                               le64_to_cpu(old.disk_num_bytes),
-                                               0, root->root_key.objectid,
+                                               disk_bytenr, num_bytes, 0,
+                                               root->root_key.objectid,
                                                key.objectid, key.offset -
-                                               le64_to_cpu(old.offset));
+                                               extent_offset);
                                BUG_ON(ret);
-                               *hint_byte = old_disk_bytenr;
+                               inode_sub_bytes(inode,
+                                               extent_end - key.offset);
+                               *hint_byte = disk_bytenr;
                        }
-               }
 
-               if (search_start >= end) {
-                       ret = 0;
-                       goto out;
+                       if (end == extent_end)
+                               break;
+
+                       if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
+                               path->slots[0]++;
+                               goto next_slot;
+                       }
+
+                       ret = btrfs_del_items(trans, root, path, del_slot,
+                                             del_nr);
+                       BUG_ON(ret);
+
+                       del_nr = 0;
+                       del_slot = 0;
+
+                       btrfs_release_path(root, path);
+                       continue;
                }
+
+               BUG_ON(1);
        }
-out:
-       btrfs_free_path(path);
-       if (locked_end > orig_locked_end) {
-               unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end,
-                             locked_end - 1, GFP_NOFS);
+
+       if (del_nr > 0) {
+               ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+               BUG_ON(ret);
        }
+
+       btrfs_free_path(path);
        return ret;
 }
 
@@ -620,23 +544,23 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot,
  * two or three.
  */
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-                             struct btrfs_root *root,
                              struct inode *inode, u64 start, u64 end)
 {
+       struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_buffer *leaf;
        struct btrfs_path *path;
        struct btrfs_file_extent_item *fi;
        struct btrfs_key key;
+       struct btrfs_key new_key;
        u64 bytenr;
        u64 num_bytes;
        u64 extent_end;
        u64 orig_offset;
        u64 other_start;
        u64 other_end;
-       u64 split = start;
-       u64 locked_end = end;
-       int extent_type;
-       int split_end = 1;
+       u64 split;
+       int del_nr = 0;
+       int del_slot = 0;
        int ret;
 
        btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -644,12 +568,10 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        BUG_ON(!path);
 again:
+       split = start;
        key.objectid = inode->i_ino;
        key.type = BTRFS_EXTENT_DATA_KEY;
-       if (split == start)
-               key.offset = split;
-       else
-               key.offset = split - 1;
+       key.offset = split;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret > 0 && path->slots[0] > 0)
@@ -661,8 +583,8 @@ again:
               key.type != BTRFS_EXTENT_DATA_KEY);
        fi = btrfs_item_ptr(leaf, path->slots[0],
                            struct btrfs_file_extent_item);
-       extent_type = btrfs_file_extent_type(leaf, fi);
-       BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC);
+       BUG_ON(btrfs_file_extent_type(leaf, fi) !=
+              BTRFS_FILE_EXTENT_PREALLOC);
        extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
        BUG_ON(key.offset > start || extent_end < end);
 
@@ -670,150 +592,91 @@ again:
        num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
        orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi);
 
-       if (key.offset == start)
-               split = end;
-
-       if (key.offset == start && extent_end == end) {
-               int del_nr = 0;
-               int del_slot = 0;
-               other_start = end;
-               other_end = 0;
-               if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-                                    bytenr, &other_start, &other_end)) {
-                       extent_end = other_end;
-                       del_slot = path->slots[0] + 1;
-                       del_nr++;
-                       ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-                                               0, root->root_key.objectid,
-                                               inode->i_ino, orig_offset);
-                       BUG_ON(ret);
-               }
-               other_start = 0;
-               other_end = start;
-               if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
-                                    bytenr, &other_start, &other_end)) {
-                       key.offset = other_start;
-                       del_slot = path->slots[0];
-                       del_nr++;
-                       ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-                                               0, root->root_key.objectid,
-                                               inode->i_ino, orig_offset);
-                       BUG_ON(ret);
-               }
-               split_end = 0;
-               if (del_nr == 0) {
-                       btrfs_set_file_extent_type(leaf, fi,
-                                                  BTRFS_FILE_EXTENT_REG);
-                       goto done;
+       while (start > key.offset || end < extent_end) {
+               if (key.offset == start)
+                       split = end;
+
+               memcpy(&new_key, &key, sizeof(new_key));
+               new_key.offset = split;
+               ret = btrfs_duplicate_item(trans, root, path, &new_key);
+               if (ret == -EAGAIN) {
+                       btrfs_release_path(root, path);
+                       goto again;
                }
+               BUG_ON(ret < 0);
 
-               fi = btrfs_item_ptr(leaf, del_slot - 1,
+               leaf = path->nodes[0];
+               fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                                    struct btrfs_file_extent_item);
-               btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
                btrfs_set_file_extent_num_bytes(leaf, fi,
-                                               extent_end - key.offset);
+                                               split - key.offset);
+
+               fi = btrfs_item_ptr(leaf, path->slots[0],
+                                   struct btrfs_file_extent_item);
+
+               btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
+               btrfs_set_file_extent_num_bytes(leaf, fi,
+                                               extent_end - split);
                btrfs_mark_buffer_dirty(leaf);
 
-               ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+               ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
+                                          root->root_key.objectid,
+                                          inode->i_ino, orig_offset);
                BUG_ON(ret);
-               goto release;
-       } else if (split == start) {
-               if (locked_end < extent_end) {
-                       ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-                                       locked_end, extent_end - 1, GFP_NOFS);
-                       if (!ret) {
-                               btrfs_release_path(root, path);
-                               lock_extent(&BTRFS_I(inode)->io_tree,
-                                       locked_end, extent_end - 1, GFP_NOFS);
-                               locked_end = extent_end;
-                               goto again;
-                       }
-                       locked_end = extent_end;
-               }
-               btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset);
-       } else  {
-               BUG_ON(key.offset != start);
-               key.offset = split;
-               btrfs_set_file_extent_offset(leaf, fi, key.offset -
-                                            orig_offset);
-               btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split);
-               btrfs_set_item_key_safe(trans, root, path, &key);
-               extent_end = split;
-       }
 
-       if (extent_end == end) {
-               split_end = 0;
-               extent_type = BTRFS_FILE_EXTENT_REG;
-       }
-       if (extent_end == end && split == start) {
-               other_start = end;
-               other_end = 0;
-               if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-                                    bytenr, &other_start, &other_end)) {
-                       path->slots[0]++;
-                       fi = btrfs_item_ptr(leaf, path->slots[0],
-                                           struct btrfs_file_extent_item);
-                       key.offset = split;
-                       btrfs_set_item_key_safe(trans, root, path, &key);
-                       btrfs_set_file_extent_offset(leaf, fi, key.offset -
-                                                    orig_offset);
-                       btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                       other_end - split);
-                       goto done;
-               }
-       }
-       if (extent_end == end && split == end) {
-               other_start = 0;
-               other_end = start;
-               if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino,
-                                    bytenr, &other_start, &other_end)) {
+               if (split == start) {
+                       key.offset = start;
+               } else {
+                       BUG_ON(start != key.offset);
                        path->slots[0]--;
-                       fi = btrfs_item_ptr(leaf, path->slots[0],
-                                           struct btrfs_file_extent_item);
-                       btrfs_set_file_extent_num_bytes(leaf, fi, extent_end -
-                                                       other_start);
-                       goto done;
+                       extent_end = end;
                }
        }
 
-       btrfs_mark_buffer_dirty(leaf);
-
-       ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
-                                  root->root_key.objectid,
-                                  inode->i_ino, orig_offset);
-       BUG_ON(ret);
-       btrfs_release_path(root, path);
-
-       key.offset = start;
-       ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi));
-       BUG_ON(ret);
-
-       leaf = path->nodes[0];
        fi = btrfs_item_ptr(leaf, path->slots[0],
                            struct btrfs_file_extent_item);
-       btrfs_set_file_extent_generation(leaf, fi, trans->transid);
-       btrfs_set_file_extent_type(leaf, fi, extent_type);
-       btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr);
-       btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
-       btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset);
-       btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset);
-       btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
-       btrfs_set_file_extent_compression(leaf, fi, 0);
-       btrfs_set_file_extent_encryption(leaf, fi, 0);
-       btrfs_set_file_extent_other_encoding(leaf, fi, 0);
-done:
-       btrfs_mark_buffer_dirty(leaf);
 
-release:
-       btrfs_release_path(root, path);
-       if (split_end && split == start) {
-               split = end;
-               goto again;
+       other_start = end;
+       other_end = 0;
+       if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
+                            bytenr, &other_start, &other_end)) {
+               extent_end = other_end;
+               del_slot = path->slots[0] + 1;
+               del_nr++;
+               ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+                                       0, root->root_key.objectid,
+                                       inode->i_ino, orig_offset);
+               BUG_ON(ret);
        }
-       if (locked_end > end) {
-               unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
-                             GFP_NOFS);
+       other_start = 0;
+       other_end = start;
+       if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
+                            bytenr, &other_start, &other_end)) {
+               key.offset = other_start;
+               del_slot = path->slots[0];
+               del_nr++;
+               ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+                                       0, root->root_key.objectid,
+                                       inode->i_ino, orig_offset);
+               BUG_ON(ret);
        }
+       if (del_nr == 0) {
+               btrfs_set_file_extent_type(leaf, fi,
+                                          BTRFS_FILE_EXTENT_REG);
+               btrfs_mark_buffer_dirty(leaf);
+               goto out;
+       }
+
+       fi = btrfs_item_ptr(leaf, del_slot - 1,
+                           struct btrfs_file_extent_item);
+       btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
+       btrfs_set_file_extent_num_bytes(leaf, fi,
+                                       extent_end - key.offset);
+       btrfs_mark_buffer_dirty(leaf);
+
+       ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+       BUG_ON(ret);
+out:
        btrfs_free_path(path);
        return 0;
 }
index b3ad168..5440bab 100644 (file)
@@ -88,13 +88,14 @@ static noinline int cow_file_range(struct inode *inode,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
 
-static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
+static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
+                                    struct inode *inode,  struct inode *dir)
 {
        int err;
 
-       err = btrfs_init_acl(inode, dir);
+       err = btrfs_init_acl(trans, inode, dir);
        if (!err)
-               err = btrfs_xattr_security_init(inode, dir);
+               err = btrfs_xattr_security_init(trans, inode, dir);
        return err;
 }
 
@@ -188,8 +189,18 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
        btrfs_mark_buffer_dirty(leaf);
        btrfs_free_path(path);
 
+       /*
+        * we're an inline extent, so nobody can
+        * extend the file past i_size without locking
+        * a page we already have locked.
+        *
+        * We must do any isize and inode updates
+        * before we unlock the pages.  Otherwise we
+        * could end up racing with unlink.
+        */
        BTRFS_I(inode)->disk_i_size = inode->i_size;
        btrfs_update_inode(trans, root, inode);
+
        return 0;
 fail:
        btrfs_free_path(path);
@@ -230,8 +241,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
                return 1;
        }
 
-       ret = btrfs_drop_extents(trans, root, inode, start,
-                                aligned_end, aligned_end, start,
+       ret = btrfs_drop_extents(trans, inode, start, aligned_end,
                                 &hint_byte, 1);
        BUG_ON(ret);
 
@@ -416,7 +426,6 @@ again:
                                                    start, end,
                                                    total_compressed, pages);
                }
-               btrfs_end_transaction(trans, root);
                if (ret == 0) {
                        /*
                         * inline extent creation worked, we don't need
@@ -430,9 +439,11 @@ again:
                             EXTENT_CLEAR_DELALLOC |
                             EXTENT_CLEAR_ACCOUNTING |
                             EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK);
-                       ret = 0;
+
+                       btrfs_end_transaction(trans, root);
                        goto free_pages_out;
                }
+               btrfs_end_transaction(trans, root);
        }
 
        if (will_compress) {
@@ -543,7 +554,6 @@ static noinline int submit_compressed_extents(struct inode *inode,
        if (list_empty(&async_cow->extents))
                return 0;
 
-       trans = btrfs_join_transaction(root, 1);
 
        while (!list_empty(&async_cow->extents)) {
                async_extent = list_entry(async_cow->extents.next,
@@ -590,19 +600,15 @@ retry:
                lock_extent(io_tree, async_extent->start,
                            async_extent->start + async_extent->ram_size - 1,
                            GFP_NOFS);
-               /*
-                * here we're doing allocation and writeback of the
-                * compressed pages
-                */
-               btrfs_drop_extent_cache(inode, async_extent->start,
-                                       async_extent->start +
-                                       async_extent->ram_size - 1, 0);
 
+               trans = btrfs_join_transaction(root, 1);
                ret = btrfs_reserve_extent(trans, root,
                                           async_extent->compressed_size,
                                           async_extent->compressed_size,
                                           0, alloc_hint,
                                           (u64)-1, &ins, 1);
+               btrfs_end_transaction(trans, root);
+
                if (ret) {
                        int i;
                        for (i = 0; i < async_extent->nr_pages; i++) {
@@ -618,6 +624,14 @@ retry:
                        goto retry;
                }
 
+               /*
+                * here we're doing allocation and writeback of the
+                * compressed pages
+                */
+               btrfs_drop_extent_cache(inode, async_extent->start,
+                                       async_extent->start +
+                                       async_extent->ram_size - 1, 0);
+
                em = alloc_extent_map(GFP_NOFS);
                em->start = async_extent->start;
                em->len = async_extent->ram_size;
@@ -649,8 +663,6 @@ retry:
                                               BTRFS_ORDERED_COMPRESSED);
                BUG_ON(ret);
 
-               btrfs_end_transaction(trans, root);
-
                /*
                 * clear dirty, set writeback and unlock the pages.
                 */
@@ -672,13 +684,11 @@ retry:
                                    async_extent->nr_pages);
 
                BUG_ON(ret);
-               trans = btrfs_join_transaction(root, 1);
                alloc_hint = ins.objectid + ins.offset;
                kfree(async_extent);
                cond_resched();
        }
 
-       btrfs_end_transaction(trans, root);
        return 0;
 }
 
@@ -742,6 +752,7 @@ static noinline int cow_file_range(struct inode *inode,
                                     EXTENT_CLEAR_DIRTY |
                                     EXTENT_SET_WRITEBACK |
                                     EXTENT_END_WRITEBACK);
+
                        *nr_written = *nr_written +
                             (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
                        *page_started = 1;
@@ -1596,7 +1607,6 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
                                       struct inode *inode, u64 file_pos,
                                       u64 disk_bytenr, u64 disk_num_bytes,
                                       u64 num_bytes, u64 ram_bytes,
-                                      u64 locked_end,
                                       u8 compression, u8 encryption,
                                       u16 other_encoding, int extent_type)
 {
@@ -1622,9 +1632,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
         * the caller is expected to unpin it and allow it to be merged
         * with the others.
         */
-       ret = btrfs_drop_extents(trans, root, inode, file_pos,
-                                file_pos + num_bytes, locked_end,
-                                file_pos, &hint, 0);
+       ret = btrfs_drop_extents(trans, inode, file_pos, file_pos + num_bytes,
+                                &hint, 0);
        BUG_ON(ret);
 
        ins.objectid = inode->i_ino;
@@ -1730,23 +1739,32 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                }
        }
 
-       trans = btrfs_join_transaction(root, 1);
-
        if (!ordered_extent)
                ordered_extent = btrfs_lookup_ordered_extent(inode, start);
        BUG_ON(!ordered_extent);
-       if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags))
-               goto nocow;
+       if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
+               BUG_ON(!list_empty(&ordered_extent->list));
+               ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+               if (!ret) {
+                       trans = btrfs_join_transaction(root, 1);
+                       ret = btrfs_update_inode(trans, root, inode);
+                       BUG_ON(ret);
+                       btrfs_end_transaction(trans, root);
+               }
+               goto out;
+       }
 
        lock_extent(io_tree, ordered_extent->file_offset,
                    ordered_extent->file_offset + ordered_extent->len - 1,
                    GFP_NOFS);
 
+       trans = btrfs_join_transaction(root, 1);
+
        if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
                compressed = 1;
        if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
                BUG_ON(compressed);
-               ret = btrfs_mark_extent_written(trans, root, inode,
+               ret = btrfs_mark_extent_written(trans, inode,
                                                ordered_extent->file_offset,
                                                ordered_extent->file_offset +
                                                ordered_extent->len);
@@ -1758,8 +1776,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                                                ordered_extent->disk_len,
                                                ordered_extent->len,
                                                ordered_extent->len,
-                                               ordered_extent->file_offset +
-                                               ordered_extent->len,
                                                compressed, 0, 0,
                                                BTRFS_FILE_EXTENT_REG);
                unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
@@ -1770,22 +1786,20 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
        unlock_extent(io_tree, ordered_extent->file_offset,
                    ordered_extent->file_offset + ordered_extent->len - 1,
                    GFP_NOFS);
-nocow:
        add_pending_csums(trans, inode, ordered_extent->file_offset,
                          &ordered_extent->list);
 
-       mutex_lock(&BTRFS_I(inode)->extent_mutex);
-       btrfs_ordered_update_i_size(inode, ordered_extent);
-       btrfs_update_inode(trans, root, inode);
-       btrfs_remove_ordered_extent(inode, ordered_extent);
-       mutex_unlock(&BTRFS_I(inode)->extent_mutex);
-
+       /* this also removes the ordered extent from the tree */
+       btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+       ret = btrfs_update_inode(trans, root, inode);
+       BUG_ON(ret);
+       btrfs_end_transaction(trans, root);
+out:
        /* once for us */
        btrfs_put_ordered_extent(ordered_extent);
        /* once for the tree */
        btrfs_put_ordered_extent(ordered_extent);
 
-       btrfs_end_transaction(trans, root);
        return 0;
 }
 
@@ -2008,6 +2022,54 @@ zeroit:
        return -EIO;
 }
 
+struct delayed_iput {
+       struct list_head list;
+       struct inode *inode;
+};
+
+void btrfs_add_delayed_iput(struct inode *inode)
+{
+       struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
+       struct delayed_iput *delayed;
+
+       if (atomic_add_unless(&inode->i_count, -1, 1))
+               return;
+
+       delayed = kmalloc(sizeof(*delayed), GFP_NOFS | __GFP_NOFAIL);
+       delayed->inode = inode;
+
+       spin_lock(&fs_info->delayed_iput_lock);
+       list_add_tail(&delayed->list, &fs_info->delayed_iputs);
+       spin_unlock(&fs_info->delayed_iput_lock);
+}
+
+void btrfs_run_delayed_iputs(struct btrfs_root *root)
+{
+       LIST_HEAD(list);
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct delayed_iput *delayed;
+       int empty;
+
+       spin_lock(&fs_info->delayed_iput_lock);
+       empty = list_empty(&fs_info->delayed_iputs);
+       spin_unlock(&fs_info->delayed_iput_lock);
+       if (empty)
+               return;
+
+       down_read(&root->fs_info->cleanup_work_sem);
+       spin_lock(&fs_info->delayed_iput_lock);
+       list_splice_init(&fs_info->delayed_iputs, &list);
+       spin_unlock(&fs_info->delayed_iput_lock);
+
+       while (!list_empty(&list)) {
+               delayed = list_entry(list.next, struct delayed_iput, list);
+               list_del(&delayed->list);
+               iput(delayed->inode);
+               kfree(delayed);
+       }
+       up_read(&root->fs_info->cleanup_work_sem);
+}
+
 /*
  * This creates an orphan entry for the given inode in case something goes
  * wrong in the middle of an unlink/truncate.
@@ -2080,16 +2142,17 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
        struct inode *inode;
        int ret = 0, nr_unlink = 0, nr_truncate = 0;
 
-       path = btrfs_alloc_path();
-       if (!path)
+       if (!xchg(&root->clean_orphans, 0))
                return;
+
+       path = btrfs_alloc_path();
+       BUG_ON(!path);
        path->reada = -1;
 
        key.objectid = BTRFS_ORPHAN_OBJECTID;
        btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
        key.offset = (u64)-1;
 
-
        while (1) {
                ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
                if (ret < 0) {
@@ -2834,37 +2897,40 @@ out:
  * min_type is the minimum key type to truncate down to.  If set to 0, this
  * will kill all the items on this inode, including the INODE_ITEM_KEY.
  */
-noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
-                                       struct btrfs_root *root,
-                                       struct inode *inode,
-                                       u64 new_size, u32 min_type)
+int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
+                              struct btrfs_root *root,
+                              struct inode *inode,
+                              u64 new_size, u32 min_type)
 {
-       int ret;
        struct btrfs_path *path;
-       struct btrfs_key key;
-       struct btrfs_key found_key;
-       u32 found_type = (u8)-1;
        struct extent_buffer *leaf;
        struct btrfs_file_extent_item *fi;
+       struct btrfs_key key;
+       struct btrfs_key found_key;
        u64 extent_start = 0;
        u64 extent_num_bytes = 0;
        u64 extent_offset = 0;
        u64 item_end = 0;
+       u64 mask = root->sectorsize - 1;
+       u32 found_type = (u8)-1;
        int found_extent;
        int del_item;
        int pending_del_nr = 0;
        int pending_del_slot = 0;
        int extent_type = -1;
        int encoding;
-       u64 mask = root->sectorsize - 1;
+       int ret;
+       int err = 0;
+
+       BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
        if (root->ref_cows)
                btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
+
        path = btrfs_alloc_path();
        BUG_ON(!path);
        path->reada = -1;
 
-       /* FIXME, add redo link to tree so we don't leak on crash */
        key.objectid = inode->i_ino;
        key.offset = (u64)-1;
        key.type = (u8)-1;
@@ -2872,17 +2938,17 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 search_again:
        path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       if (ret < 0)
-               goto error;
+       if (ret < 0) {
+               err = ret;
+               goto out;
+       }
 
        if (ret > 0) {
                /* there are no items in the tree for us to truncate, we're
                 * done
                 */
-               if (path->slots[0] == 0) {
-                       ret = 0;
-                       goto error;
-               }
+               if (path->slots[0] == 0)
+                       goto out;
                path->slots[0]--;
        }
 
@@ -2917,28 +2983,17 @@ search_again:
                        }
                        item_end--;
                }
-               if (item_end < new_size) {
-                       if (found_type == BTRFS_DIR_ITEM_KEY)
-                               found_type = BTRFS_INODE_ITEM_KEY;
-                       else if (found_type == BTRFS_EXTENT_ITEM_KEY)
-                               found_type = BTRFS_EXTENT_DATA_KEY;
-                       else if (found_type == BTRFS_EXTENT_DATA_KEY)
-                               found_type = BTRFS_XATTR_ITEM_KEY;
-                       else if (found_type == BTRFS_XATTR_ITEM_KEY)
-                               found_type = BTRFS_INODE_REF_KEY;
-                       else if (found_type)
-                               found_type--;
-                       else
+               if (found_type > min_type) {
+                       del_item = 1;
+               } else {
+                       if (item_end < new_size)
                                break;
-                       btrfs_set_key_type(&key, found_type);
-                       goto next;
+                       if (found_key.offset >= new_size)
+                               del_item = 1;
+                       else
+                               del_item = 0;
                }
-               if (found_key.offset >= new_size)
-                       del_item = 1;
-               else
-                       del_item = 0;
                found_extent = 0;
-
                /* FIXME, shrink the extent if the ref count is only 1 */
                if (found_type != BTRFS_EXTENT_DATA_KEY)
                        goto delete;
@@ -3025,42 +3080,36 @@ delete:
                                                inode->i_ino, extent_offset);
                        BUG_ON(ret);
                }
-next:
-               if (path->slots[0] == 0) {
-                       if (pending_del_nr)
-                               goto del_pending;
-                       btrfs_release_path(root, path);
-                       if (found_type == BTRFS_INODE_ITEM_KEY)
-                               break;
-                       goto search_again;
-               }
 
-               path->slots[0]--;
-               if (pending_del_nr &&
-                   path->slots[0] + 1 != pending_del_slot) {
-                       struct btrfs_key debug;
-del_pending:
-                       btrfs_item_key_to_cpu(path->nodes[0], &debug,
-                                             pending_del_slot);
-                       ret = btrfs_del_items(trans, root, path,
-                                             pending_del_slot,
-                                             pending_del_nr);
-                       BUG_ON(ret);
-                       pending_del_nr = 0;
+               if (found_type == BTRFS_INODE_ITEM_KEY)
+                       break;
+
+               if (path->slots[0] == 0 ||
+                   path->slots[0] != pending_del_slot) {
+                       if (root->ref_cows) {
+                               err = -EAGAIN;
+                               goto out;
+                       }
+                       if (pending_del_nr) {
+                               ret = btrfs_del_items(trans, root, path,
+                                               pending_del_slot,
+                                               pending_del_nr);
+                               BUG_ON(ret);
+                               pending_del_nr = 0;
+                       }
                        btrfs_release_path(root, path);
-                       if (found_type == BTRFS_INODE_ITEM_KEY)
-                               break;
                        goto search_again;
+               } else {
+                       path->slots[0]--;
                }
        }
-       ret = 0;
-error:
+out:
        if (pending_del_nr) {
                ret = btrfs_del_items(trans, root, path, pending_del_slot,
                                      pending_del_nr);
        }
        btrfs_free_path(path);
-       return ret;
+       return err;
 }
 
 /*
@@ -3180,10 +3229,6 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        if (size <= hole_start)
                return 0;
 
-       err = btrfs_truncate_page(inode->i_mapping, inode->i_size);
-       if (err)
-               return err;
-
        while (1) {
                struct btrfs_ordered_extent *ordered;
                btrfs_wait_ordered_range(inode, hole_start,
@@ -3196,9 +3241,6 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
                btrfs_put_ordered_extent(ordered);
        }
 
-       trans = btrfs_start_transaction(root, 1);
-       btrfs_set_trans_block_group(trans, inode);
-
        cur_offset = hole_start;
        while (1) {
                em = btrfs_get_extent(inode, NULL, 0, cur_offset,
@@ -3206,40 +3248,120 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
                BUG_ON(IS_ERR(em) || !em);
                last_byte = min(extent_map_end(em), block_end);
                last_byte = (last_byte + mask) & ~mask;
-               if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
+               if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
                        u64 hint_byte = 0;
                        hole_size = last_byte - cur_offset;
-                       err = btrfs_drop_extents(trans, root, inode,
-                                                cur_offset,
-                                                cur_offset + hole_size,
-                                                block_end,
-                                                cur_offset, &hint_byte, 1);
-                       if (err)
-                               break;
 
-                       err = btrfs_reserve_metadata_space(root, 1);
+                       err = btrfs_reserve_metadata_space(root, 2);
                        if (err)
                                break;
 
+                       trans = btrfs_start_transaction(root, 1);
+                       btrfs_set_trans_block_group(trans, inode);
+
+                       err = btrfs_drop_extents(trans, inode, cur_offset,
+                                                cur_offset + hole_size,
+                                                &hint_byte, 1);
+                       BUG_ON(err);
+
                        err = btrfs_insert_file_extent(trans, root,
                                        inode->i_ino, cur_offset, 0,
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
+                       BUG_ON(err);
+
                        btrfs_drop_extent_cache(inode, hole_start,
                                        last_byte - 1, 0);
-                       btrfs_unreserve_metadata_space(root, 1);
+
+                       btrfs_end_transaction(trans, root);
+                       btrfs_unreserve_metadata_space(root, 2);
                }
                free_extent_map(em);
                cur_offset = last_byte;
-               if (err || cur_offset >= block_end)
+               if (cur_offset >= block_end)
                        break;
        }
 
-       btrfs_end_transaction(trans, root);
        unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
        return err;
 }
 
+static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
+       unsigned long nr;
+       int ret;
+
+       if (attr->ia_size == inode->i_size)
+               return 0;
+
+       if (attr->ia_size > inode->i_size) {
+               unsigned long limit;
+               limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+               if (attr->ia_size > inode->i_sb->s_maxbytes)
+                       return -EFBIG;
+               if (limit != RLIM_INFINITY && attr->ia_size > limit) {
+                       send_sig(SIGXFSZ, current, 0);
+                       return -EFBIG;
+               }
+       }
+
+       ret = btrfs_reserve_metadata_space(root, 1);
+       if (ret)
+               return ret;
+
+       trans = btrfs_start_transaction(root, 1);
+       btrfs_set_trans_block_group(trans, inode);
+
+       ret = btrfs_orphan_add(trans, inode);
+       BUG_ON(ret);
+
+       nr = trans->blocks_used;
+       btrfs_end_transaction(trans, root);
+       btrfs_unreserve_metadata_space(root, 1);
+       btrfs_btree_balance_dirty(root, nr);
+
+       if (attr->ia_size > inode->i_size) {
+               ret = btrfs_cont_expand(inode, attr->ia_size);
+               if (ret) {
+                       btrfs_truncate(inode);
+                       return ret;
+               }
+
+               i_size_write(inode, attr->ia_size);
+               btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
+
+               trans = btrfs_start_transaction(root, 1);
+               btrfs_set_trans_block_group(trans, inode);
+
+               ret = btrfs_update_inode(trans, root, inode);
+               BUG_ON(ret);
+               if (inode->i_nlink > 0) {
+                       ret = btrfs_orphan_del(trans, inode);
+                       BUG_ON(ret);
+               }
+               nr = trans->blocks_used;
+               btrfs_end_transaction(trans, root);
+               btrfs_btree_balance_dirty(root, nr);
+               return 0;
+       }
+
+       /*
+        * We're truncating a file that used to have good data down to
+        * zero. Make sure it gets into the ordered flush list so that
+        * any new writes get down to disk quickly.
+        */
+       if (attr->ia_size == 0)
+               BTRFS_I(inode)->ordered_data_close = 1;
+
+       /* we don't support swapfiles, so vmtruncate shouldn't fail */
+       ret = vmtruncate(inode, attr->ia_size);
+       BUG_ON(ret);
+
+       return 0;
+}
+
 static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
@@ -3250,23 +3372,14 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               if (attr->ia_size > inode->i_size) {
-                       err = btrfs_cont_expand(inode, attr->ia_size);
-                       if (err)
-                               return err;
-               } else if (inode->i_size > 0 &&
-                          attr->ia_size == 0) {
-
-                       /* we're truncating a file that used to have good
-                        * data down to zero.  Make sure it gets into
-                        * the ordered flush list so that any new writes
-                        * get down to disk quickly.
-                        */
-                       BTRFS_I(inode)->ordered_data_close = 1;
-               }
+               err = btrfs_setattr_size(inode, attr);
+               if (err)
+                       return err;
        }
+       attr->ia_valid &= ~ATTR_SIZE;
 
-       err = inode_setattr(inode, attr);
+       if (attr->ia_valid)
+               err = inode_setattr(inode, attr);
 
        if (!err && ((attr->ia_valid & ATTR_MODE)))
                err = btrfs_acl_chmod(inode);
@@ -3287,36 +3400,43 @@ void btrfs_delete_inode(struct inode *inode)
        }
        btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
+       if (root->fs_info->log_root_recovering) {
+               BUG_ON(!list_empty(&BTRFS_I(inode)->i_orphan));
+               goto no_delete;
+       }
+
        if (inode->i_nlink > 0) {
                BUG_ON(btrfs_root_refs(&root->root_item) != 0);
                goto no_delete;
        }
 
        btrfs_i_size_write(inode, 0);
-       trans = btrfs_join_transaction(root, 1);
 
-       btrfs_set_trans_block_group(trans, inode);
-       ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
-       if (ret) {
-               btrfs_orphan_del(NULL, inode);
-               goto no_delete_lock;
-       }
+       while (1) {
+               trans = btrfs_start_transaction(root, 1);
+               btrfs_set_trans_block_group(trans, inode);
+               ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
 
-       btrfs_orphan_del(trans, inode);
+               if (ret != -EAGAIN)
+                       break;
 
-       nr = trans->blocks_used;
-       clear_inode(inode);
+               nr = trans->blocks_used;
+               btrfs_end_transaction(trans, root);
+               trans = NULL;
+               btrfs_btree_balance_dirty(root, nr);
+       }
 
-       btrfs_end_transaction(trans, root);
-       btrfs_btree_balance_dirty(root, nr);
-       return;
+       if (ret == 0) {
+               ret = btrfs_orphan_del(trans, inode);
+               BUG_ON(ret);
+       }
 
-no_delete_lock:
        nr = trans->blocks_used;
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root, nr);
 no_delete:
        clear_inode(inode);
+       return;
 }
 
 /*
@@ -3569,7 +3689,6 @@ static noinline void init_btrfs_i(struct inode *inode)
        INIT_LIST_HEAD(&BTRFS_I(inode)->ordered_operations);
        RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
        btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
-       mutex_init(&BTRFS_I(inode)->extent_mutex);
        mutex_init(&BTRFS_I(inode)->log_mutex);
 }
 
@@ -3695,6 +3814,13 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
        }
        srcu_read_unlock(&root->fs_info->subvol_srcu, index);
 
+       if (root != sub_root) {
+               down_read(&root->fs_info->cleanup_work_sem);
+               if (!(inode->i_sb->s_flags & MS_RDONLY))
+                       btrfs_orphan_cleanup(sub_root);
+               up_read(&root->fs_info->cleanup_work_sem);
+       }
+
        return inode;
 }
 
@@ -4219,7 +4345,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_inode_security(inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -4290,7 +4416,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_inode_security(inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -4336,6 +4462,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        if (inode->i_nlink == 0)
                return -ENOENT;
 
+       /* do not allow sys_link's with other subvols of the same device */
+       if (root->objectid != BTRFS_I(inode)->root->objectid)
+               return -EPERM;
+
        /*
         * 1 item for inode ref
         * 2 items for dir items
@@ -4423,7 +4553,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        drop_on_err = 1;
 
-       err = btrfs_init_inode_security(inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir);
        if (err)
                goto out_fail;
 
@@ -5074,17 +5204,20 @@ static void btrfs_truncate(struct inode *inode)
        unsigned long nr;
        u64 mask = root->sectorsize - 1;
 
-       if (!S_ISREG(inode->i_mode))
-               return;
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+       if (!S_ISREG(inode->i_mode)) {
+               WARN_ON(1);
                return;
+       }
 
        ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
        if (ret)
                return;
+
        btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
+       btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
 
        trans = btrfs_start_transaction(root, 1);
+       btrfs_set_trans_block_group(trans, inode);
 
        /*
         * setattr is responsible for setting the ordered_data_close flag,
@@ -5106,21 +5239,32 @@ static void btrfs_truncate(struct inode *inode)
        if (inode->i_size == 0 && BTRFS_I(inode)->ordered_data_close)
                btrfs_add_ordered_operation(trans, root, inode);
 
-       btrfs_set_trans_block_group(trans, inode);
-       btrfs_i_size_write(inode, inode->i_size);
+       while (1) {
+               ret = btrfs_truncate_inode_items(trans, root, inode,
+                                                inode->i_size,
+                                                BTRFS_EXTENT_DATA_KEY);
+               if (ret != -EAGAIN)
+                       break;
 
-       ret = btrfs_orphan_add(trans, inode);
-       if (ret)
-               goto out;
-       /* FIXME, add redo link to tree so we don't leak on crash */
-       ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
-                                     BTRFS_EXTENT_DATA_KEY);
-       btrfs_update_inode(trans, root, inode);
+               ret = btrfs_update_inode(trans, root, inode);
+               BUG_ON(ret);
+
+               nr = trans->blocks_used;
+               btrfs_end_transaction(trans, root);
+               btrfs_btree_balance_dirty(root, nr);
+
+               trans = btrfs_start_transaction(root, 1);
+               btrfs_set_trans_block_group(trans, inode);
+       }
 
-       ret = btrfs_orphan_del(trans, inode);
+       if (ret == 0 && inode->i_nlink > 0) {
+               ret = btrfs_orphan_del(trans, inode);
+               BUG_ON(ret);
+       }
+
+       ret = btrfs_update_inode(trans, root, inode);
        BUG_ON(ret);
 
-out:
        nr = trans->blocks_used;
        ret = btrfs_end_transaction_throttle(trans, root);
        BUG_ON(ret);
@@ -5217,9 +5361,9 @@ void btrfs_destroy_inode(struct inode *inode)
 
        spin_lock(&root->list_lock);
        if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
-               printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan"
-                      " list\n", inode->i_ino);
-               dump_stack();
+               printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n",
+                      inode->i_ino);
+               list_del_init(&BTRFS_I(inode)->i_orphan);
        }
        spin_unlock(&root->list_lock);
 
@@ -5476,7 +5620,7 @@ out_fail:
  * some fairly slow code that needs optimization. This walks the list
  * of all the inodes with pending delalloc and forces them to disk.
  */
-int btrfs_start_delalloc_inodes(struct btrfs_root *root)
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
        struct list_head *head = &root->fs_info->delalloc_inodes;
        struct btrfs_inode *binode;
@@ -5495,7 +5639,10 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root)
                spin_unlock(&root->fs_info->delalloc_lock);
                if (inode) {
                        filemap_flush(inode->i_mapping);
-                       iput(inode);
+                       if (delay_iput)
+                               btrfs_add_delayed_iput(inode);
+                       else
+                               iput(inode);
                }
                cond_resched();
                spin_lock(&root->fs_info->delalloc_lock);
@@ -5569,7 +5716,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_inode_security(inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -5641,10 +5788,10 @@ out_fail:
        return err;
 }
 
-static int prealloc_file_range(struct btrfs_trans_handle *trans,
-                              struct inode *inode, u64 start, u64 end,
-                              u64 locked_end, u64 alloc_hint, int mode)
+static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
+                              u64 alloc_hint, int mode)
 {
+       struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key ins;
        u64 alloc_size;
@@ -5655,43 +5802,56 @@ static int prealloc_file_range(struct btrfs_trans_handle *trans,
        while (num_bytes > 0) {
                alloc_size = min(num_bytes, root->fs_info->max_extent);
 
-               ret = btrfs_reserve_metadata_space(root, 1);
-               if (ret)
-                       goto out;
+               trans = btrfs_start_transaction(root, 1);
 
                ret = btrfs_reserve_extent(trans, root, alloc_size,
                                           root->sectorsize, 0, alloc_hint,
                                           (u64)-1, &ins, 1);
                if (ret) {
                        WARN_ON(1);
-                       goto out;
+                       goto stop_trans;
+               }
+
+               ret = btrfs_reserve_metadata_space(root, 3);
+               if (ret) {
+                       btrfs_free_reserved_extent(root, ins.objectid,
+                                                  ins.offset);
+                       goto stop_trans;
                }
+
                ret = insert_reserved_file_extent(trans, inode,
                                                  cur_offset, ins.objectid,
                                                  ins.offset, ins.offset,
-                                                 ins.offset, locked_end,
-                                                 0, 0, 0,
+                                                 ins.offset, 0, 0, 0,
                                                  BTRFS_FILE_EXTENT_PREALLOC);
                BUG_ON(ret);
                btrfs_drop_extent_cache(inode, cur_offset,
                                        cur_offset + ins.offset -1, 0);
+
                num_bytes -= ins.offset;
                cur_offset += ins.offset;
                alloc_hint = ins.objectid + ins.offset;
-               btrfs_unreserve_metadata_space(root, 1);
-       }
-out:
-       if (cur_offset > start) {
+
                inode->i_ctime = CURRENT_TIME;
                BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
                if (!(mode & FALLOC_FL_KEEP_SIZE) &&
-                   cur_offset > i_size_read(inode))
-                       btrfs_i_size_write(inode, cur_offset);
+                   cur_offset > inode->i_size) {
+                       i_size_write(inode, cur_offset);
+                       btrfs_ordered_update_i_size(inode, cur_offset, NULL);
+               }
+
                ret = btrfs_update_inode(trans, root, inode);
                BUG_ON(ret);
+
+               btrfs_end_transaction(trans, root);
+               btrfs_unreserve_metadata_space(root, 3);
        }
+       return ret;
 
+stop_trans:
+       btrfs_end_transaction(trans, root);
        return ret;
+
 }
 
 static long btrfs_fallocate(struct inode *inode, int mode,
@@ -5705,8 +5865,6 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        u64 locked_end;
        u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
        struct extent_map *em;
-       struct btrfs_trans_handle *trans;
-       struct btrfs_root *root;
        int ret;
 
        alloc_start = offset & ~mask;
@@ -5725,9 +5883,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                        goto out;
        }
 
-       root = BTRFS_I(inode)->root;
-
-       ret = btrfs_check_data_free_space(root, inode,
+       ret = btrfs_check_data_free_space(BTRFS_I(inode)->root, inode,
                                          alloc_end - alloc_start);
        if (ret)
                goto out;
@@ -5736,12 +5892,6 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        while (1) {
                struct btrfs_ordered_extent *ordered;
 
-               trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
-               if (!trans) {
-                       ret = -EIO;
-                       goto out_free;
-               }
-
                /* the extent lock is ordered inside the running
                 * transaction
                 */
@@ -5755,8 +5905,6 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                        btrfs_put_ordered_extent(ordered);
                        unlock_extent(&BTRFS_I(inode)->io_tree,
                                      alloc_start, locked_end, GFP_NOFS);
-                       btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-
                        /*
                         * we can't wait on the range with the transaction
                         * running or with the extent lock held
@@ -5777,10 +5925,12 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                BUG_ON(IS_ERR(em) || !em);
                last_byte = min(extent_map_end(em), alloc_end);
                last_byte = (last_byte + mask) & ~mask;
-               if (em->block_start == EXTENT_MAP_HOLE) {
-                       ret = prealloc_file_range(trans, inode, cur_offset,
-                                       last_byte, locked_end + 1,
-                                       alloc_hint, mode);
+               if (em->block_start == EXTENT_MAP_HOLE ||
+                   (cur_offset >= inode->i_size &&
+                    !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
+                       ret = prealloc_file_range(inode,
+                                                 cur_offset, last_byte,
+                                                 alloc_hint, mode);
                        if (ret < 0) {
                                free_extent_map(em);
                                break;
@@ -5799,9 +5949,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
                      GFP_NOFS);
 
-       btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-out_free:
-       btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
+       btrfs_free_reserved_data_space(BTRFS_I(inode)->root, inode,
+                                      alloc_end - alloc_start);
 out:
        mutex_unlock(&inode->i_mutex);
        return ret;
index cdbb054..645a179 100644 (file)
@@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root,
        u64 objectid;
        u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
        u64 index = 0;
-       unsigned long nr = 1;
 
        /*
         * 1 - inode item
@@ -290,7 +289,7 @@ static noinline int create_subvol(struct btrfs_root *root,
        btrfs_set_root_generation(&root_item, trans->transid);
        btrfs_set_root_level(&root_item, 0);
        btrfs_set_root_refs(&root_item, 1);
-       btrfs_set_root_used(&root_item, 0);
+       btrfs_set_root_used(&root_item, leaf->len);
        btrfs_set_root_last_snapshot(&root_item, 0);
 
        memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
@@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
-       nr = trans->blocks_used;
        err = btrfs_commit_transaction(trans, root);
        if (err && !ret)
                ret = err;
 
        btrfs_unreserve_metadata_space(root, 6);
-       btrfs_btree_balance_dirty(root, nr);
        return ret;
 }
 
 static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                           char *name, int namelen)
 {
+       struct inode *inode;
        struct btrfs_pending_snapshot *pending_snapshot;
        struct btrfs_trans_handle *trans;
-       int ret = 0;
-       int err;
-       unsigned long nr = 0;
+       int ret;
 
        if (!root->ref_cows)
                return -EINVAL;
@@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
         */
        ret = btrfs_reserve_metadata_space(root, 6);
        if (ret)
-               goto fail_unlock;
+               goto fail;
 
        pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
        if (!pending_snapshot) {
                ret = -ENOMEM;
                btrfs_unreserve_metadata_space(root, 6);
-               goto fail_unlock;
+               goto fail;
        }
        pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
        if (!pending_snapshot->name) {
                ret = -ENOMEM;
                kfree(pending_snapshot);
                btrfs_unreserve_metadata_space(root, 6);
-               goto fail_unlock;
+               goto fail;
        }
        memcpy(pending_snapshot->name, name, namelen);
        pending_snapshot->name[namelen] = '\0';
@@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        pending_snapshot->root = root;
        list_add(&pending_snapshot->list,
                 &trans->transaction->pending_snapshots);
-       err = btrfs_commit_transaction(trans, root);
+       ret = btrfs_commit_transaction(trans, root);
+       BUG_ON(ret);
+       btrfs_unreserve_metadata_space(root, 6);
 
-fail_unlock:
-       btrfs_btree_balance_dirty(root, nr);
+       inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+       if (IS_ERR(inode)) {
+               ret = PTR_ERR(inode);
+               goto fail;
+       }
+       BUG_ON(!inode);
+       d_instantiate(dentry, inode);
+       ret = 0;
+fail:
        return ret;
 }
 
@@ -1027,8 +1032,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        BUG_ON(!trans);
 
        /* punch hole in destination first */
-       btrfs_drop_extents(trans, root, inode, off, off + len,
-                          off + len, 0, &hint_byte, 1);
+       btrfs_drop_extents(trans, inode, off, off + len, &hint_byte, 1);
 
        /* clone data */
        key.objectid = src->i_ino;
index 5799bc4..b10a49d 100644 (file)
@@ -291,16 +291,16 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
 
 /*
  * remove an ordered extent from the tree.  No references are dropped
- * but, anyone waiting on this extent is woken up.
+ * and you must wake_up entry->wait.  You must hold the tree mutex
+ * while you call this function.
  */
-int btrfs_remove_ordered_extent(struct inode *inode,
+static int __btrfs_remove_ordered_extent(struct inode *inode,
                                struct btrfs_ordered_extent *entry)
 {
        struct btrfs_ordered_inode_tree *tree;
        struct rb_node *node;
 
        tree = &BTRFS_I(inode)->ordered_tree;
-       mutex_lock(&tree->mutex);
        node = &entry->rb_node;
        rb_erase(node, &tree->tree);
        tree->last = NULL;
@@ -326,16 +326,34 @@ int btrfs_remove_ordered_extent(struct inode *inode,
        }
        spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
 
+       return 0;
+}
+
+/*
+ * remove an ordered extent from the tree.  No references are dropped
+ * but any waiters are woken.
+ */
+int btrfs_remove_ordered_extent(struct inode *inode,
+                               struct btrfs_ordered_extent *entry)
+{
+       struct btrfs_ordered_inode_tree *tree;
+       int ret;
+
+       tree = &BTRFS_I(inode)->ordered_tree;
+       mutex_lock(&tree->mutex);
+       ret = __btrfs_remove_ordered_extent(inode, entry);
        mutex_unlock(&tree->mutex);
        wake_up(&entry->wait);
-       return 0;
+
+       return ret;
 }
 
 /*
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+                              int nocow_only, int delay_iput)
 {
        struct list_head splice;
        struct list_head *cur;
@@ -372,7 +390,10 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
                if (inode) {
                        btrfs_start_ordered_extent(inode, ordered, 1);
                        btrfs_put_ordered_extent(ordered);
-                       iput(inode);
+                       if (delay_iput)
+                               btrfs_add_delayed_iput(inode);
+                       else
+                               iput(inode);
                } else {
                        btrfs_put_ordered_extent(ordered);
                }
@@ -430,7 +451,7 @@ again:
                                btrfs_wait_ordered_range(inode, 0, (u64)-1);
                        else
                                filemap_flush(inode->i_mapping);
-                       iput(inode);
+                       btrfs_add_delayed_iput(inode);
                }
 
                cond_resched();
@@ -589,7 +610,7 @@ out:
  * After an extent is done, call this to conditionally update the on disk
  * i_size.  i_size is updated to cover any fully written part of the file.
  */
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                                struct btrfs_ordered_extent *ordered)
 {
        struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
@@ -597,18 +618,30 @@ int btrfs_ordered_update_i_size(struct inode *inode,
        u64 disk_i_size;
        u64 new_i_size;
        u64 i_size_test;
+       u64 i_size = i_size_read(inode);
        struct rb_node *node;
+       struct rb_node *prev = NULL;
        struct btrfs_ordered_extent *test;
+       int ret = 1;
+
+       if (ordered)
+               offset = entry_end(ordered);
 
        mutex_lock(&tree->mutex);
        disk_i_size = BTRFS_I(inode)->disk_i_size;
 
+       /* truncate file */
+       if (disk_i_size > i_size) {
+               BTRFS_I(inode)->disk_i_size = i_size;
+               ret = 0;
+               goto out;
+       }
+
        /*
         * if the disk i_size is already at the inode->i_size, or
         * this ordered extent is inside the disk i_size, we're done
         */
-       if (disk_i_size >= inode->i_size ||
-           ordered->file_offset + ordered->len <= disk_i_size) {
+       if (disk_i_size == i_size || offset <= disk_i_size) {
                goto out;
        }
 
@@ -616,8 +649,7 @@ int btrfs_ordered_update_i_size(struct inode *inode,
         * we can't update the disk_isize if there are delalloc bytes
         * between disk_i_size and  this ordered extent
         */
-       if (test_range_bit(io_tree, disk_i_size,
-                          ordered->file_offset + ordered->len - 1,
+       if (test_range_bit(io_tree, disk_i_size, offset - 1,
                           EXTENT_DELALLOC, 0, NULL)) {
                goto out;
        }
@@ -626,20 +658,32 @@ int btrfs_ordered_update_i_size(struct inode *inode,
         * if we find an ordered extent then we can't update disk i_size
         * yet
         */
-       node = &ordered->rb_node;
-       while (1) {
-               node = rb_prev(node);
-               if (!node)
-                       break;
+       if (ordered) {
+               node = rb_prev(&ordered->rb_node);
+       } else {
+               prev = tree_search(tree, offset);
+               /*
+                * we insert file extents without involving ordered struct,
+                * so there should be no ordered struct cover this offset
+                */
+               if (prev) {
+                       test = rb_entry(prev, struct btrfs_ordered_extent,
+                                       rb_node);
+                       BUG_ON(offset_in_entry(test, offset));
+               }
+               node = prev;
+       }
+       while (node) {
                test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
                if (test->file_offset + test->len <= disk_i_size)
                        break;
-               if (test->file_offset >= inode->i_size)
+               if (test->file_offset >= i_size)
                        break;
                if (test->file_offset >= disk_i_size)
                        goto out;
+               node = rb_prev(node);
        }
-       new_i_size = min_t(u64, entry_end(ordered), i_size_read(inode));
+       new_i_size = min_t(u64, offset, i_size);
 
        /*
         * at this point, we know we can safely update i_size to at least
@@ -647,7 +691,14 @@ int btrfs_ordered_update_i_size(struct inode *inode,
         * walk forward and see if ios from higher up in the file have
         * finished.
         */
-       node = rb_next(&ordered->rb_node);
+       if (ordered) {
+               node = rb_next(&ordered->rb_node);
+       } else {
+               if (prev)
+                       node = rb_next(prev);
+               else
+                       node = rb_first(&tree->tree);
+       }
        i_size_test = 0;
        if (node) {
                /*
@@ -655,10 +706,10 @@ int btrfs_ordered_update_i_size(struct inode *inode,
                 * between our ordered extent and the next one.
                 */
                test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-               if (test->file_offset > entry_end(ordered))
+               if (test->file_offset > offset)
                        i_size_test = test->file_offset;
        } else {
-               i_size_test = i_size_read(inode);
+               i_size_test = i_size;
        }
 
        /*
@@ -667,15 +718,25 @@ int btrfs_ordered_update_i_size(struct inode *inode,
         * are no delalloc bytes in this area, it is safe to update
         * disk_i_size to the end of the region.
         */
-       if (i_size_test > entry_end(ordered) &&
-           !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1,
-                          EXTENT_DELALLOC, 0, NULL)) {
-               new_i_size = min_t(u64, i_size_test, i_size_read(inode));
+       if (i_size_test > offset &&
+           !test_range_bit(io_tree, offset, i_size_test - 1,
+                           EXTENT_DELALLOC, 0, NULL)) {
+               new_i_size = min_t(u64, i_size_test, i_size);
        }
        BTRFS_I(inode)->disk_i_size = new_i_size;
+       ret = 0;
 out:
+       /*
+        * we need to remove the ordered extent with the tree lock held
+        * so that other people calling this function don't find our fully
+        * processed ordered entry and skip updating the i_size
+        */
+       if (ordered)
+               __btrfs_remove_ordered_extent(inode, ordered);
        mutex_unlock(&tree->mutex);
-       return 0;
+       if (ordered)
+               wake_up(&ordered->wait);
+       return ret;
 }
 
 /*
index f82e874..1fe1282 100644 (file)
@@ -150,12 +150,13 @@ void btrfs_start_ordered_extent(struct inode *inode,
 int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len);
 struct btrfs_ordered_extent *
 btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset);
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                                struct btrfs_ordered_extent *ordered);
 int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only);
 int btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
 int btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                struct inode *inode);
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+                              int nocow_only, int delay_iput);
 #endif
index cfcc93c..a972868 100644 (file)
@@ -1561,6 +1561,20 @@ static int invalidate_extent_cache(struct btrfs_root *root,
        return 0;
 }
 
+static void put_inodes(struct list_head *list)
+{
+       struct inodevec *ivec;
+       while (!list_empty(list)) {
+               ivec = list_entry(list->next, struct inodevec, list);
+               list_del(&ivec->list);
+               while (ivec->nr > 0) {
+                       ivec->nr--;
+                       iput(ivec->inode[ivec->nr]);
+               }
+               kfree(ivec);
+       }
+}
+
 static int find_next_key(struct btrfs_path *path, int level,
                         struct btrfs_key *key)
 
@@ -1723,6 +1737,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
 
                btrfs_btree_balance_dirty(root, nr);
 
+               /*
+                * put inodes outside transaction, otherwise we may deadlock.
+                */
+               put_inodes(&inode_list);
+
                if (replaced && rc->stage == UPDATE_DATA_PTRS)
                        invalidate_extent_cache(root, &key, &next_key);
        }
@@ -1752,19 +1771,7 @@ out:
 
        btrfs_btree_balance_dirty(root, nr);
 
-       /*
-        * put inodes while we aren't holding the tree locks
-        */
-       while (!list_empty(&inode_list)) {
-               struct inodevec *ivec;
-               ivec = list_entry(inode_list.next, struct inodevec, list);
-               list_del(&ivec->list);
-               while (ivec->nr > 0) {
-                       ivec->nr--;
-                       iput(ivec->inode[ivec->nr]);
-               }
-               kfree(ivec);
-       }
+       put_inodes(&inode_list);
 
        if (replaced && rc->stage == UPDATE_DATA_PTRS)
                invalidate_extent_cache(root, &key, &next_key);
@@ -3534,8 +3541,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
               (unsigned long long)rc->block_group->key.objectid,
               (unsigned long long)rc->block_group->flags);
 
-       btrfs_start_delalloc_inodes(fs_info->tree_root);
-       btrfs_wait_ordered_extents(fs_info->tree_root, 0);
+       btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
+       btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0);
 
        while (1) {
                rc->extents_found = 0;
@@ -3755,6 +3762,7 @@ out:
                                       BTRFS_DATA_RELOC_TREE_OBJECTID);
                if (IS_ERR(fs_root))
                        err = PTR_ERR(fs_root);
+               btrfs_orphan_cleanup(fs_root);
        }
        return err;
 }
index 752a546..3f9b457 100644 (file)
@@ -128,6 +128,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
        substring_t args[MAX_OPT_ARGS];
        char *p, *num;
        int intarg;
+       int ret = 0;
 
        if (!options)
                return 0;
@@ -262,12 +263,18 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                case Opt_discard:
                        btrfs_set_opt(info->mount_opt, DISCARD);
                        break;
+               case Opt_err:
+                       printk(KERN_INFO "btrfs: unrecognized mount option "
+                              "'%s'\n", p);
+                       ret = -EINVAL;
+                       goto out;
                default:
                        break;
                }
        }
+out:
        kfree(options);
-       return 0;
+       return ret;
 }
 
 /*
@@ -405,8 +412,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
                return 0;
        }
 
-       btrfs_start_delalloc_inodes(root);
-       btrfs_wait_ordered_extents(root, 0);
+       btrfs_start_delalloc_inodes(root, 0);
+       btrfs_wait_ordered_extents(root, 0, 0);
 
        trans = btrfs_start_transaction(root, 1);
        ret = btrfs_commit_transaction(trans, root);
@@ -450,6 +457,8 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_puts(seq, ",notreelog");
        if (btrfs_test_opt(root, FLUSHONCOMMIT))
                seq_puts(seq, ",flushoncommit");
+       if (btrfs_test_opt(root, DISCARD))
+               seq_puts(seq, ",discard");
        if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
                seq_puts(seq, ",noacl");
        return 0;
index c207e8c..b2acc79 100644 (file)
@@ -333,6 +333,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        memset(trans, 0, sizeof(*trans));
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 
+       if (throttle)
+               btrfs_run_delayed_iputs(root);
+
        return 0;
 }
 
@@ -354,7 +357,7 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
  * those extents are sent to disk but does not wait on them
  */
 int btrfs_write_marked_extents(struct btrfs_root *root,
-                              struct extent_io_tree *dirty_pages)
+                              struct extent_io_tree *dirty_pages, int mark)
 {
        int ret;
        int err = 0;
@@ -367,7 +370,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
 
        while (1) {
                ret = find_first_extent_bit(dirty_pages, start, &start, &end,
-                                           EXTENT_DIRTY);
+                                           mark);
                if (ret)
                        break;
                while (start <= end) {
@@ -413,7 +416,7 @@ int btrfs_write_marked_extents(struct btrfs_root *root,
  * on all the pages and clear them from the dirty pages state tree
  */
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-                             struct extent_io_tree *dirty_pages)
+                             struct extent_io_tree *dirty_pages, int mark)
 {
        int ret;
        int err = 0;
@@ -425,12 +428,12 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
        unsigned long index;
 
        while (1) {
-               ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
-                                           EXTENT_DIRTY);
+               ret = find_first_extent_bit(dirty_pages, start, &start, &end,
+                                           mark);
                if (ret)
                        break;
 
-               clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
+               clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS);
                while (start <= end) {
                        index = start >> PAGE_CACHE_SHIFT;
                        start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
@@ -460,13 +463,13 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
  * those extents are on disk for transaction or log commit
  */
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-                                       struct extent_io_tree *dirty_pages)
+                               struct extent_io_tree *dirty_pages, int mark)
 {
        int ret;
        int ret2;
 
-       ret = btrfs_write_marked_extents(root, dirty_pages);
-       ret2 = btrfs_wait_marked_extents(root, dirty_pages);
+       ret = btrfs_write_marked_extents(root, dirty_pages, mark);
+       ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark);
        return ret || ret2;
 }
 
@@ -479,7 +482,8 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
                return filemap_write_and_wait(btree_inode->i_mapping);
        }
        return btrfs_write_and_wait_marked_extents(root,
-                                          &trans->transaction->dirty_pages);
+                                          &trans->transaction->dirty_pages,
+                                          EXTENT_DIRTY);
 }
 
 /*
@@ -497,13 +501,16 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
 {
        int ret;
        u64 old_root_bytenr;
+       u64 old_root_used;
        struct btrfs_root *tree_root = root->fs_info->tree_root;
 
+       old_root_used = btrfs_root_used(&root->root_item);
        btrfs_write_dirty_block_groups(trans, root);
 
        while (1) {
                old_root_bytenr = btrfs_root_bytenr(&root->root_item);
-               if (old_root_bytenr == root->node->start)
+               if (old_root_bytenr == root->node->start &&
+                   old_root_used == btrfs_root_used(&root->root_item))
                        break;
 
                btrfs_set_root_node(&root->root_item, root->node);
@@ -512,6 +519,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
                                        &root->root_item);
                BUG_ON(ret);
 
+               old_root_used = btrfs_root_used(&root->root_item);
                ret = btrfs_write_dirty_block_groups(trans, root);
                BUG_ON(ret);
        }
@@ -795,7 +803,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        memcpy(&pending->root_key, &key, sizeof(key));
 fail:
        kfree(new_root_item);
-       btrfs_unreserve_metadata_space(root, 6);
        return ret;
 }
 
@@ -807,7 +814,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
        u64 index = 0;
        struct btrfs_trans_handle *trans;
        struct inode *parent_inode;
-       struct inode *inode;
        struct btrfs_root *parent_root;
 
        parent_inode = pending->dentry->d_parent->d_inode;
@@ -839,8 +845,6 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
 
        BUG_ON(ret);
 
-       inode = btrfs_lookup_dentry(parent_inode, pending->dentry);
-       d_instantiate(pending->dentry, inode);
 fail:
        btrfs_end_transaction(trans, fs_info->fs_root);
        return ret;
@@ -994,11 +998,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                mutex_unlock(&root->fs_info->trans_mutex);
 
                if (flush_on_commit) {
-                       btrfs_start_delalloc_inodes(root);
-                       ret = btrfs_wait_ordered_extents(root, 0);
+                       btrfs_start_delalloc_inodes(root, 1);
+                       ret = btrfs_wait_ordered_extents(root, 0, 1);
                        BUG_ON(ret);
                } else if (snap_pending) {
-                       ret = btrfs_wait_ordered_extents(root, 1);
+                       ret = btrfs_wait_ordered_extents(root, 0, 1);
                        BUG_ON(ret);
                }
 
@@ -1116,6 +1120,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                current->journal_info = NULL;
 
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
+
+       if (current != root->fs_info->transaction_kthread)
+               btrfs_run_delayed_iputs(root);
+
        return ret;
 }
 
index d4e3e7a..93c7ccb 100644 (file)
@@ -107,10 +107,10 @@ void btrfs_throttle(struct btrfs_root *root);
 int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root);
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-                                       struct extent_io_tree *dirty_pages);
+                               struct extent_io_tree *dirty_pages, int mark);
 int btrfs_write_marked_extents(struct btrfs_root *root,
-                                       struct extent_io_tree *dirty_pages);
+                               struct extent_io_tree *dirty_pages, int mark);
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-                                       struct extent_io_tree *dirty_pages);
+                               struct extent_io_tree *dirty_pages, int mark);
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 #endif
index 741666a..4a9434b 100644 (file)
@@ -542,8 +542,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
 
        saved_nbytes = inode_get_bytes(inode);
        /* drop any overlapping extents */
-       ret = btrfs_drop_extents(trans, root, inode,
-                        start, extent_end, extent_end, start, &alloc_hint, 1);
+       ret = btrfs_drop_extents(trans, inode, start, extent_end,
+                                &alloc_hint, 1);
        BUG_ON(ret);
 
        if (found_type == BTRFS_FILE_EXTENT_REG ||
@@ -930,6 +930,17 @@ out_nowrite:
        return 0;
 }
 
+static int insert_orphan_item(struct btrfs_trans_handle *trans,
+                             struct btrfs_root *root, u64 offset)
+{
+       int ret;
+       ret = btrfs_find_orphan_item(root, offset);
+       if (ret > 0)
+               ret = btrfs_insert_orphan_item(trans, root, offset);
+       return ret;
+}
+
+
 /*
  * There are a few corners where the link count of the file can't
  * be properly maintained during replay.  So, instead of adding
@@ -997,9 +1008,13 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
        }
        BTRFS_I(inode)->index_cnt = (u64)-1;
 
-       if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) {
-               ret = replay_dir_deletes(trans, root, NULL, path,
-                                        inode->i_ino, 1);
+       if (inode->i_nlink == 0) {
+               if (S_ISDIR(inode->i_mode)) {
+                       ret = replay_dir_deletes(trans, root, NULL, path,
+                                                inode->i_ino, 1);
+                       BUG_ON(ret);
+               }
+               ret = insert_orphan_item(trans, root, inode->i_ino);
                BUG_ON(ret);
        }
        btrfs_free_path(path);
@@ -1587,7 +1602,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                /* inode keys are done during the first stage */
                if (key.type == BTRFS_INODE_ITEM_KEY &&
                    wc->stage == LOG_WALK_REPLAY_INODES) {
-                       struct inode *inode;
                        struct btrfs_inode_item *inode_item;
                        u32 mode;
 
@@ -1603,31 +1617,16 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                                             eb, i, &key);
                        BUG_ON(ret);
 
-                       /* for regular files, truncate away
-                        * extents past the new EOF
+                       /* for regular files, make sure corresponding
+                        * orhpan item exist. extents past the new EOF
+                        * will be truncated later by orphan cleanup.
                         */
                        if (S_ISREG(mode)) {
-                               inode = read_one_inode(root,
-                                                      key.objectid);
-                               BUG_ON(!inode);
-
-                               ret = btrfs_truncate_inode_items(wc->trans,
-                                       root, inode, inode->i_size,
-                                       BTRFS_EXTENT_DATA_KEY);
+                               ret = insert_orphan_item(wc->trans, root,
+                                                        key.objectid);
                                BUG_ON(ret);
-
-                               /* if the nlink count is zero here, the iput
-                                * will free the inode.  We bump it to make
-                                * sure it doesn't get freed until the link
-                                * count fixup is done
-                                */
-                               if (inode->i_nlink == 0) {
-                                       btrfs_inc_nlink(inode);
-                                       btrfs_update_inode(wc->trans,
-                                                          root, inode);
-                               }
-                               iput(inode);
                        }
+
                        ret = link_to_fixup_dir(wc->trans, root,
                                                path, key.objectid);
                        BUG_ON(ret);
@@ -1977,10 +1976,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 {
        int index1;
        int index2;
+       int mark;
        int ret;
        struct btrfs_root *log = root->log_root;
        struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
-       u64 log_transid = 0;
+       unsigned long log_transid = 0;
 
        mutex_lock(&root->log_mutex);
        index1 = root->log_transid % 2;
@@ -2014,24 +2014,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                goto out;
        }
 
+       log_transid = root->log_transid;
+       if (log_transid % 2 == 0)
+               mark = EXTENT_DIRTY;
+       else
+               mark = EXTENT_NEW;
+
        /* we start IO on  all the marked extents here, but we don't actually
         * wait for them until later.
         */
-       ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
+       ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);
        BUG_ON(ret);
 
        btrfs_set_root_node(&log->root_item, log->node);
 
        root->log_batch = 0;
-       log_transid = root->log_transid;
        root->log_transid++;
        log->log_transid = root->log_transid;
        root->log_start_pid = 0;
        smp_mb();
        /*
-        * log tree has been flushed to disk, new modifications of
-        * the log will be written to new positions. so it's safe to
-        * allow log writers to go in.
+        * IO has been started, blocks of the log tree have WRITTEN flag set
+        * in their headers. new modifications of the log will be written to
+        * new positions. so it's safe to allow log writers to go in.
         */
        mutex_unlock(&root->log_mutex);
 
@@ -2052,7 +2057,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
        index2 = log_root_tree->log_transid % 2;
        if (atomic_read(&log_root_tree->log_commit[index2])) {
-               btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+               btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
                wait_log_commit(trans, log_root_tree,
                                log_root_tree->log_transid);
                mutex_unlock(&log_root_tree->log_mutex);
@@ -2072,16 +2077,17 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
         * check the full commit flag again
         */
        if (root->fs_info->last_trans_log_full_commit == trans->transid) {
-               btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+               btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
                mutex_unlock(&log_root_tree->log_mutex);
                ret = -EAGAIN;
                goto out_wake_log_root;
        }
 
        ret = btrfs_write_and_wait_marked_extents(log_root_tree,
-                               &log_root_tree->dirty_log_pages);
+                               &log_root_tree->dirty_log_pages,
+                               EXTENT_DIRTY | EXTENT_NEW);
        BUG_ON(ret);
-       btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+       btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 
        btrfs_set_super_log_root(&root->fs_info->super_for_commit,
                                log_root_tree->node->start);
@@ -2147,12 +2153,12 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
 
        while (1) {
                ret = find_first_extent_bit(&log->dirty_log_pages,
-                                   0, &start, &end, EXTENT_DIRTY);
+                               0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
                if (ret)
                        break;
 
-               clear_extent_dirty(&log->dirty_log_pages,
-                                  start, end, GFP_NOFS);
+               clear_extent_bits(&log->dirty_log_pages, start, end,
+                                 EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
        }
 
        if (log->log_transid > 0) {
index 7eda483..198cff2 100644 (file)
@@ -2209,7 +2209,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                max_chunk_size = 10 * calc_size;
                min_stripe_size = 64 * 1024 * 1024;
        } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-               max_chunk_size = 4 * calc_size;
+               max_chunk_size = 256 * 1024 * 1024;
                min_stripe_size = 32 * 1024 * 1024;
        } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
                calc_size = 8 * 1024 * 1024;
index b6dd596..193b58f 100644 (file)
@@ -85,22 +85,23 @@ out:
        return ret;
 }
 
-int __btrfs_setxattr(struct inode *inode, const char *name,
-                           const void *value, size_t size, int flags)
+static int do_setxattr(struct btrfs_trans_handle *trans,
+                      struct inode *inode, const char *name,
+                      const void *value, size_t size, int flags)
 {
        struct btrfs_dir_item *di;
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct btrfs_trans_handle *trans;
        struct btrfs_path *path;
-       int ret = 0, mod = 0;
+       size_t name_len = strlen(name);
+       int ret = 0;
+
+       if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
+               return -ENOSPC;
 
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
 
-       trans = btrfs_join_transaction(root, 1);
-       btrfs_set_trans_block_group(trans, inode);
-
        /* first lets see if we already have this xattr */
        di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
                                strlen(name), -1);
@@ -118,15 +119,12 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
                }
 
                ret = btrfs_delete_one_dir_name(trans, root, path, di);
-               if (ret)
-                       goto out;
+               BUG_ON(ret);
                btrfs_release_path(root, path);
 
                /* if we don't have a value then we are removing the xattr */
-               if (!value) {
-                       mod = 1;
+               if (!value)
                        goto out;
-               }
        } else {
                btrfs_release_path(root, path);
 
@@ -138,20 +136,45 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
        }
 
        /* ok we have to create a completely new xattr */
-       ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
-                                     value, size, inode->i_ino);
+       ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
+                                     name, name_len, value, size);
+       BUG_ON(ret);
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+                    struct inode *inode, const char *name,
+                    const void *value, size_t size, int flags)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       int ret;
+
+       if (trans)
+               return do_setxattr(trans, inode, name, value, size, flags);
+
+       ret = btrfs_reserve_metadata_space(root, 2);
        if (ret)
-               goto out;
-       mod = 1;
+               return ret;
 
-out:
-       if (mod) {
-               inode->i_ctime = CURRENT_TIME;
-               ret = btrfs_update_inode(trans, root, inode);
+       trans = btrfs_start_transaction(root, 1);
+       if (!trans) {
+               ret = -ENOMEM;
+               goto out;
        }
+       btrfs_set_trans_block_group(trans, inode);
 
-       btrfs_end_transaction(trans, root);
-       btrfs_free_path(path);
+       ret = do_setxattr(trans, inode, name, value, size, flags);
+       if (ret)
+               goto out;
+
+       inode->i_ctime = CURRENT_TIME;
+       ret = btrfs_update_inode(trans, root, inode);
+       BUG_ON(ret);
+out:
+       btrfs_end_transaction_throttle(trans, root);
+       btrfs_unreserve_metadata_space(root, 2);
        return ret;
 }
 
@@ -314,7 +337,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
-       return __btrfs_setxattr(dentry->d_inode, name, value, size, flags);
+
+       return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+                               flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
@@ -329,10 +354,13 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
 
        if (!btrfs_is_valid_xattr(name))
                return -EOPNOTSUPP;
-       return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+
+       return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+                               XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+                             struct inode *inode, struct inode *dir)
 {
        int err;
        size_t len;
@@ -354,7 +382,7 @@ int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
        } else {
                strcpy(name, XATTR_SECURITY_PREFIX);
                strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-               err = __btrfs_setxattr(inode, name, value, len, 0);
+               err = __btrfs_setxattr(trans, inode, name, value, len, 0);
                kfree(name);
        }
 
index c71e9c3..721efa0 100644 (file)
@@ -27,15 +27,16 @@ extern struct xattr_handler *btrfs_xattr_handlers[];
 
 extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
                void *buffer, size_t size);
-extern int __btrfs_setxattr(struct inode *inode, const char *name,
-               const void *value, size_t size, int flags);
-
+extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+                           struct inode *inode, const char *name,
+                           const void *value, size_t size, int flags);
 extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
                void *buffer, size_t size);
 extern int btrfs_setxattr(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags);
 extern int btrfs_removexattr(struct dentry *dentry, const char *name);
 
-extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir);
+extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+                                    struct inode *inode, struct inode *dir);
 
 #endif /* __XATTR__ */
index 4012885..e82adc2 100644 (file)
@@ -1206,7 +1206,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
         * NOTE: filesystems with their own locking have to handle this
         * on their own.
         */
-       if (dio->flags & DIO_LOCKING) {
+       if (flags & DIO_LOCKING) {
                if (unlikely((rw & WRITE) && retval < 0)) {
                        loff_t isize = i_size_read(inode);
                        if (end > isize)
index 2dda5ad..8f006a0 100644 (file)
@@ -62,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
                struct inode *lower_inode =
                        ecryptfs_inode_to_lower(dentry->d_inode);
 
-               fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
+               fsstack_copy_attr_all(dentry->d_inode, lower_inode);
        }
 out:
        return rc;
index 056fed6..429ca0b 100644 (file)
@@ -626,9 +626,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        lower_new_dir_dentry->d_inode, lower_new_dentry);
        if (rc)
                goto out_lock;
-       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
+       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
        if (new_dir != old_dir)
-               fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
+               fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        dput(lower_new_dentry->d_parent);
@@ -967,7 +967,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        rc = notify_change(lower_dentry, ia);
        mutex_unlock(&lower_dentry->d_inode->i_mutex);
 out:
-       fsstack_copy_attr_all(inode, lower_inode, NULL);
+       fsstack_copy_attr_all(inode, lower_inode);
        return rc;
 }
 
index 101fe4c..567bc4b 100644 (file)
@@ -189,7 +189,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
                init_special_inode(inode, lower_inode->i_mode,
                                   lower_inode->i_rdev);
        dentry->d_op = &ecryptfs_dops;
-       fsstack_copy_attr_all(inode, lower_inode, NULL);
+       fsstack_copy_attr_all(inode, lower_inode);
        /* This size will be overwritten for real files w/ headers and
         * other metadata */
        fsstack_copy_inode_size(inode, lower_inode);
index 623a5cc..632b02e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -826,7 +826,9 @@ static int de_thread(struct task_struct *tsk)
                attach_pid(tsk, PIDTYPE_PID,  task_pid(leader));
                transfer_pid(leader, tsk, PIDTYPE_PGID);
                transfer_pid(leader, tsk, PIDTYPE_SID);
+
                list_replace_rcu(&leader->tasks, &tsk->tasks);
+               list_replace_init(&leader->sibling, &tsk->sibling);
 
                tsk->group_leader = tsk;
                leader->group_leader = tsk;
@@ -1761,17 +1763,20 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        struct mm_struct *mm = current->mm;
        struct linux_binfmt * binfmt;
        struct inode * inode;
-       struct file * file;
        const struct cred *old_cred;
        struct cred *cred;
        int retval = 0;
        int flag = 0;
        int ispipe = 0;
-       unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
        char **helper_argv = NULL;
        int helper_argc = 0;
        int dump_count = 0;
        static atomic_t core_dump_count = ATOMIC_INIT(0);
+       struct coredump_params cprm = {
+               .signr = signr,
+               .regs = regs,
+               .limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+       };
 
        audit_core_dumps(signr);
 
@@ -1827,15 +1832,15 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        ispipe = format_corename(corename, signr);
        unlock_kernel();
 
-       if ((!ispipe) && (core_limit < binfmt->min_coredump))
+       if ((!ispipe) && (cprm.limit < binfmt->min_coredump))
                goto fail_unlock;
 
        if (ispipe) {
-               if (core_limit == 0) {
+               if (cprm.limit == 0) {
                        /*
                         * Normally core limits are irrelevant to pipes, since
                         * we're not writing to the file system, but we use
-                        * core_limit of 0 here as a speacial value. Any
+                        * cprm.limit of 0 here as a speacial value. Any
                         * non-zero limit gets set to RLIM_INFINITY below, but
                         * a limit of 0 skips the dump.  This is a consistent
                         * way to catch recursive crashes.  We can still crash
@@ -1868,25 +1873,25 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
                        goto fail_dropcount;
                }
 
-               core_limit = RLIM_INFINITY;
+               cprm.limit = RLIM_INFINITY;
 
                /* SIGPIPE can happen, but it's just never processed */
                if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
-                               &file)) {
+                               &cprm.file)) {
                        printk(KERN_INFO "Core dump to %s pipe failed\n",
                               corename);
                        goto fail_dropcount;
                }
        } else
-               file = filp_open(corename,
+               cprm.file = filp_open(corename,
                                 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
                                 0600);
-       if (IS_ERR(file))
+       if (IS_ERR(cprm.file))
                goto fail_dropcount;
-       inode = file->f_path.dentry->d_inode;
+       inode = cprm.file->f_path.dentry->d_inode;
        if (inode->i_nlink > 1)
                goto close_fail;        /* multiple links - don't dump */
-       if (!ispipe && d_unhashed(file->f_path.dentry))
+       if (!ispipe && d_unhashed(cprm.file->f_path.dentry))
                goto close_fail;
 
        /* AK: actually i see no reason to not allow this for named pipes etc.,
@@ -1899,21 +1904,22 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
         */
        if (inode->i_uid != current_fsuid())
                goto close_fail;
-       if (!file->f_op)
+       if (!cprm.file->f_op)
                goto close_fail;
-       if (!file->f_op->write)
+       if (!cprm.file->f_op->write)
                goto close_fail;
-       if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+       if (!ispipe &&
+           do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0)
                goto close_fail;
 
-       retval = binfmt->core_dump(signr, regs, file, core_limit);
+       retval = binfmt->core_dump(&cprm);
 
        if (retval)
                current->signal->group_exit_code |= 0x80;
 close_fail:
        if (ispipe && core_pipe_limit)
-               wait_for_dump_helpers(file);
-       filp_close(file, NULL);
+               wait_for_dump_helpers(cprm.file);
+       filp_close(cprm.file, NULL);
 fail_dropcount:
        if (dump_count)
                atomic_dec(&core_dump_count);
index e5f6774..9acf7e8 100644 (file)
@@ -2,7 +2,6 @@ config EXT4_FS
        tristate "The Extended 4 (ext4) filesystem"
        select JBD2
        select CRC16
-       select FS_JOURNAL_INFO
        help
          This is the next generation of the ext3 filesystem.
 
index b192c66..4dcddf8 100644 (file)
@@ -10,7 +10,6 @@ config GFS2_FS
        select SLOW_WORK
        select QUOTA
        select QUOTACTL
-       select FS_JOURNAL_INFO
        help
          A cluster filesystem.
 
index 3ff32fa..6e220f4 100644 (file)
@@ -125,7 +125,7 @@ static struct inode *gfs2_iget_skip(struct super_block *sb,
  * directory entry when gfs2_inode_lookup() is invoked. Part of the code
  * segment inside gfs2_inode_lookup code needs to get moved around.
  *
- * Clean up I_LOCK and I_NEW as well.
+ * Clears I_NEW as well.
  **/
 
 void gfs2_set_iop(struct inode *inode)
index 06c1f02..03dfeb2 100644 (file)
@@ -113,7 +113,7 @@ static void wake_up_inode(struct inode *inode)
         * Prevent speculative execution through spin_unlock(&inode_lock);
         */
        smp_mb();
-       wake_up_bit(&inode->i_state, __I_LOCK);
+       wake_up_bit(&inode->i_state, __I_NEW);
 }
 
 /**
@@ -690,17 +690,17 @@ void unlock_new_inode(struct inode *inode)
        }
 #endif
        /*
-        * This is special!  We do not need the spinlock when clearing I_LOCK,
+        * This is special!  We do not need the spinlock when clearing I_NEW,
         * because we're guaranteed that nobody else tries to do anything about
         * the state of the inode when it is locked, as we just created it (so
-        * there can be no old holders that haven't tested I_LOCK).
+        * there can be no old holders that haven't tested I_NEW).
         * However we must emit the memory barrier so that other CPUs reliably
-        * see the clearing of I_LOCK after the other inode initialisation has
+        * see the clearing of I_NEW after the other inode initialisation has
         * completed.
         */
        smp_mb();
-       WARN_ON((inode->i_state & (I_LOCK|I_NEW)) != (I_LOCK|I_NEW));
-       inode->i_state &= ~(I_LOCK|I_NEW);
+       WARN_ON(!(inode->i_state & I_NEW));
+       inode->i_state &= ~I_NEW;
        wake_up_inode(inode);
 }
 EXPORT_SYMBOL(unlock_new_inode);
@@ -731,7 +731,7 @@ static struct inode *get_new_inode(struct super_block *sb,
                                goto set_failed;
 
                        __inode_add_to_lists(sb, head, inode);
-                       inode->i_state = I_LOCK|I_NEW;
+                       inode->i_state = I_NEW;
                        spin_unlock(&inode_lock);
 
                        /* Return the locked inode with I_NEW set, the
@@ -778,7 +778,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb,
                if (!old) {
                        inode->i_ino = ino;
                        __inode_add_to_lists(sb, head, inode);
-                       inode->i_state = I_LOCK|I_NEW;
+                       inode->i_state = I_NEW;
                        spin_unlock(&inode_lock);
 
                        /* Return the locked inode with I_NEW set, the
@@ -1083,7 +1083,7 @@ int insert_inode_locked(struct inode *inode)
        ino_t ino = inode->i_ino;
        struct hlist_head *head = inode_hashtable + hash(sb, ino);
 
-       inode->i_state |= I_LOCK|I_NEW;
+       inode->i_state |= I_NEW;
        while (1) {
                struct hlist_node *node;
                struct inode *old = NULL;
@@ -1120,7 +1120,7 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval,
        struct super_block *sb = inode->i_sb;
        struct hlist_head *head = inode_hashtable + hash(sb, hashval);
 
-       inode->i_state |= I_LOCK|I_NEW;
+       inode->i_state |= I_NEW;
 
        while (1) {
                struct hlist_node *node;
@@ -1510,7 +1510,7 @@ EXPORT_SYMBOL(inode_wait);
  * until the deletion _might_ have completed.  Callers are responsible
  * to recheck inode state.
  *
- * It doesn't matter if I_LOCK is not set initially, a call to
+ * It doesn't matter if I_NEW is not set initially, a call to
  * wake_up_inode() after removing from the hash list will DTRT.
  *
  * This is called with inode_lock held.
@@ -1518,8 +1518,8 @@ EXPORT_SYMBOL(inode_wait);
 static void __wait_on_freeing_inode(struct inode *inode)
 {
        wait_queue_head_t *wq;
-       DEFINE_WAIT_BIT(wait, &inode->i_state, __I_LOCK);
-       wq = bit_waitqueue(&inode->i_state, __I_LOCK);
+       DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
+       wq = bit_waitqueue(&inode->i_state, __I_NEW);
        prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
        spin_unlock(&inode_lock);
        schedule();
index a840898..4e28bee 100644 (file)
@@ -1,6 +1,5 @@
 config JBD
        tristate
-       select FS_JOURNAL_INFO
        help
          This is a generic journalling layer for block devices.  It is
          currently used by the ext3 file system, but it could also be
index 0f7d1ce..f32f346 100644 (file)
@@ -1,7 +1,6 @@
 config JBD2
        tristate
        select CRC32
-       select FS_JOURNAL_INFO
        help
          This is a generic journaling layer for block devices that support
          both 32-bit and 64-bit block numbers.  It is currently used by
index f26e4d0..d945ea7 100644 (file)
@@ -1292,7 +1292,7 @@ int txCommit(tid_t tid,           /* transaction identifier */
                 */
                /*
                 * I believe this code is no longer needed.  Splitting I_LOCK
-                * into two bits, I_LOCK and I_SYNC should prevent this
+                * into two bits, I_NEW and I_SYNC should prevent this
                 * deadlock as well.  But since I don't have a JFS testload
                 * to verify this, only a trivial s/I_LOCK/I_SYNC/ was done.
                 * Joern
index d2783c8..dad4b80 100644 (file)
@@ -1764,7 +1764,7 @@ do_last:
 
        path_to_nameidata(&path, &nd);
        error = -EISDIR;
-       if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
+       if (S_ISDIR(path.dentry->d_inode->i_mode))
                goto exit;
 ok:
        /*
index faab127..7d70d63 100644 (file)
@@ -2068,7 +2068,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  * create_mnt_ns - creates a private namespace and adds a root filesystem
  * @mnt: pointer to the new root filesystem mountpoint
  */
-static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
+struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
 {
        struct mnt_namespace *new_ns;
 
@@ -2080,6 +2080,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
        }
        return new_ns;
 }
+EXPORT_SYMBOL(create_mnt_ns);
 
 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
                char __user *, type, unsigned long, flags, void __user *, data)
index d5b112b..ce907ef 100644 (file)
@@ -2648,13 +2648,21 @@ out_freepage:
 static int nfs_follow_remote_path(struct vfsmount *root_mnt,
                const char *export_path, struct vfsmount *mnt_target)
 {
+       struct mnt_namespace *ns_private;
        struct nameidata nd;
        struct super_block *s;
        int ret;
 
+       ns_private = create_mnt_ns(root_mnt);
+       ret = PTR_ERR(ns_private);
+       if (IS_ERR(ns_private))
+               goto out_mntput;
+
        ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
                        export_path, LOOKUP_FOLLOW, &nd);
 
+       put_mnt_ns(ns_private);
+
        if (ret != 0)
                goto out_err;
 
index 1225af7..251da07 100644 (file)
@@ -2,7 +2,6 @@ config NILFS2_FS
        tristate "NILFS2 file system support (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        select CRC32
-       select FS_JOURNAL_INFO
        help
          NILFS2 is a log-structured file system (LFS) supporting continuous
          snapshotting.  In addition to versioning capability of the entire
index 9938034..dc2505a 100644 (file)
@@ -530,7 +530,7 @@ err_corrupt_attr:
  * the ntfs inode.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *    i_flags is set to 0 and we have no business touching it.  Only an ioctl()
  *    is allowed to write to them. We should of course be honouring them but
@@ -1207,7 +1207,7 @@ err_out:
  * necessary fields in @vi as well as initializing the ntfs inode.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *
  * Return 0 on success and -errno on error.  In the error case, the inode will
@@ -1474,7 +1474,7 @@ err_out:
  * normal directory inodes.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *
  * Return 0 on success and -errno on error.  In the error case, the inode will
index 43d79da..37ba29f 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -906,17 +906,6 @@ void free_pipe_info(struct inode *inode)
 }
 
 static struct vfsmount *pipe_mnt __read_mostly;
-static int pipefs_delete_dentry(struct dentry *dentry)
-{
-       /*
-        * At creation time, we pretended this dentry was hashed
-        * (by clearing DCACHE_UNHASHED bit in d_flags)
-        * At delete time, we restore the truth : not hashed.
-        * (so that dput() can proceed correctly)
-        */
-       dentry->d_flags |= DCACHE_UNHASHED;
-       return 0;
-}
 
 /*
  * pipefs_dname() is called from d_path().
@@ -928,7 +917,6 @@ static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen)
 }
 
 static const struct dentry_operations pipefs_dentry_operations = {
-       .d_delete       = pipefs_delete_dentry,
        .d_dname        = pipefs_dname,
 };
 
@@ -989,12 +977,6 @@ struct file *create_write_pipe(int flags)
        path.mnt = mntget(pipe_mnt);
 
        path.dentry->d_op = &pipefs_dentry_operations;
-       /*
-        * We dont want to publish this dentry into global dentry hash table.
-        * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
-        * This permits a working /proc/$pid/fd/XXX on pipes
-        */
-       path.dentry->d_flags &= ~DCACHE_UNHASHED;
        d_instantiate(path.dentry, inode);
 
        err = -ENFILE;
index 32fae40..2efc571 100644 (file)
@@ -60,7 +60,7 @@ const struct inode_operations ramfs_file_inode_operations = {
  */
 int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
 {
-       unsigned long npages, xpages, loop, limit;
+       unsigned long npages, xpages, loop;
        struct page *pages;
        unsigned order;
        void *data;
index ac7cd75..513f431 100644 (file)
@@ -1,7 +1,6 @@
 config REISERFS_FS
        tristate "Reiserfs support"
        select CRC32
-       select FS_JOURNAL_INFO
        help
          Stores not just filenames but the files themselves in a balanced
          tree.  Uses journalling.
index 3a28e77..290ae38 100644 (file)
@@ -2538,6 +2538,12 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
        return reiserfs_write_full_page(page, wbc);
 }
 
+static void reiserfs_truncate_failed_write(struct inode *inode)
+{
+       truncate_inode_pages(inode->i_mapping, inode->i_size);
+       reiserfs_truncate_file(inode, 0);
+}
+
 static int reiserfs_write_begin(struct file *file,
                                struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
@@ -2604,6 +2610,8 @@ static int reiserfs_write_begin(struct file *file,
        if (ret) {
                unlock_page(page);
                page_cache_release(page);
+               /* Truncate allocated blocks */
+               reiserfs_truncate_failed_write(inode);
        }
        return ret;
 }
@@ -2701,9 +2709,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
         ** transaction tracking stuff when the size changes.  So, we have
         ** to do the i_size updates here.
         */
-       pos += copied;
-
-       if (pos > inode->i_size) {
+       if (pos + copied > inode->i_size) {
                struct reiserfs_transaction_handle myth;
                lock_depth = reiserfs_write_lock_once(inode->i_sb);
                locked = true;
@@ -2721,7 +2727,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
                        goto journal_error;
 
                reiserfs_update_inode_transaction(inode);
-               inode->i_size = pos;
+               inode->i_size = pos + copied;
                /*
                 * this will just nest into our transaction.  It's important
                 * to use mark_inode_dirty so the inode gets pushed around on the
@@ -2751,6 +2757,10 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
                reiserfs_write_unlock_once(inode->i_sb, lock_depth);
        unlock_page(page);
        page_cache_release(page);
+
+       if (pos + len > inode->i_size)
+               reiserfs_truncate_failed_write(inode);
+
        return ret == 0 ? copied : ret;
 
       journal_error:
index 67716f6..4a6f7f4 100644 (file)
@@ -7,18 +7,63 @@
  * This function cannot be inlined since i_size_{read,write} is rather
  * heavy-weight on 32-bit systems
  */
-void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
 {
-       i_size_write(dst, i_size_read((struct inode *)src));
-       dst->i_blocks = src->i_blocks;
+       loff_t i_size;
+       blkcnt_t i_blocks;
+
+       /*
+        * i_size_read() includes its own seqlocking and protection from
+        * preemption (see include/linux/fs.h): we need nothing extra for
+        * that here, and prefer to avoid nesting locks than attempt to keep
+        * i_size and i_blocks in sync together.
+        */
+       i_size = i_size_read(src);
+
+       /*
+        * But if CONFIG_LBDAF (on 32-bit), we ought to make an effort to
+        * keep the two halves of i_blocks in sync despite SMP or PREEMPT -
+        * though stat's generic_fillattr() doesn't bother, and we won't be
+        * applying quotas (where i_blocks does become important) at the
+        * upper level.
+        *
+        * We don't actually know what locking is used at the lower level;
+        * but if it's a filesystem that supports quotas, it will be using
+        * i_lock as in inode_add_bytes().  tmpfs uses other locking, and
+        * its 32-bit is (just) able to exceed 2TB i_size with the aid of
+        * holes; but its i_blocks cannot carry into the upper long without
+        * almost 2TB swap - let's ignore that case.
+        */
+       if (sizeof(i_blocks) > sizeof(long))
+               spin_lock(&src->i_lock);
+       i_blocks = src->i_blocks;
+       if (sizeof(i_blocks) > sizeof(long))
+               spin_unlock(&src->i_lock);
+
+       /*
+        * If CONFIG_SMP or CONFIG_PREEMPT on 32-bit, it's vital for
+        * fsstack_copy_inode_size() to hold some lock around
+        * i_size_write(), otherwise i_size_read() may spin forever (see
+        * include/linux/fs.h).  We don't necessarily hold i_mutex when this
+        * is called, so take i_lock for that case.
+        *
+        * And if CONFIG_LBADF (on 32-bit), continue our effort to keep the
+        * two halves of i_blocks in sync despite SMP or PREEMPT: use i_lock
+        * for that case too, and do both at once by combining the tests.
+        *
+        * There is none of this locking overhead in the 64-bit case.
+        */
+       if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
+               spin_lock(&dst->i_lock);
+       i_size_write(dst, i_size);
+       dst->i_blocks = i_blocks;
+       if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
+               spin_unlock(&dst->i_lock);
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
 
-/* copy all attributes; get_nlinks is optional way to override the i_nlink
- * copying
- */
-void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-                               int (*get_nlinks)(struct inode *))
+/* copy all attributes */
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
 {
        dest->i_mode = src->i_mode;
        dest->i_uid = src->i_uid;
@@ -29,14 +74,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
        dest->i_ctime = src->i_ctime;
        dest->i_blkbits = src->i_blkbits;
        dest->i_flags = src->i_flags;
-
-       /*
-        * Update the nlinks AFTER updating the above fields, because the
-        * get_links callback may depend on them.
-        */
-       if (!get_nlinks)
-               dest->i_nlink = src->i_nlink;
-       else
-               dest->i_nlink = (*get_nlinks)(dest);
+       dest->i_nlink = src->i_nlink;
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
index 36752a6..418727a 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -355,6 +355,7 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
 {
        int ret;
        struct file *file;
+       struct address_space *mapping;
        loff_t endbyte;                 /* inclusive */
        int fput_needed;
        umode_t i_mode;
@@ -405,7 +406,28 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
                        !S_ISLNK(i_mode))
                goto out_put;
 
-       ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
+       mapping = file->f_mapping;
+       if (!mapping) {
+               ret = -EINVAL;
+               goto out_put;
+       }
+
+       ret = 0;
+       if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
+               ret = filemap_fdatawait_range(mapping, offset, endbyte);
+               if (ret < 0)
+                       goto out_put;
+       }
+
+       if (flags & SYNC_FILE_RANGE_WRITE) {
+               ret = filemap_fdatawrite_range(mapping, offset, endbyte);
+               if (ret < 0)
+                       goto out_put;
+       }
+
+       if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
+               ret = filemap_fdatawait_range(mapping, offset, endbyte);
+
 out_put:
        fput_light(file, fput_needed);
 out:
@@ -437,38 +459,3 @@ asmlinkage long SyS_sync_file_range2(long fd, long flags,
 }
 SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
 #endif
-
-/*
- * `endbyte' is inclusive
- */
-int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
-                         loff_t endbyte, unsigned int flags)
-{
-       int ret;
-
-       if (!mapping) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = 0;
-       if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
-               ret = filemap_fdatawait_range(mapping, offset, endbyte);
-               if (ret < 0)
-                       goto out;
-       }
-
-       if (flags & SYNC_FILE_RANGE_WRITE) {
-               ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
-                                               WB_SYNC_ALL);
-               if (ret < 0)
-                       goto out;
-       }
-
-       if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
-               ret = filemap_fdatawait_range(mapping, offset, endbyte);
-       }
-out:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(do_sync_mapping_range);
index 39849f8..16a6444 100644 (file)
@@ -45,7 +45,7 @@
  *
  * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the
  * read-ahead path does not lock it ("sys_read -> generic_file_aio_read ->
- * ondemand_readahead -> readpage"). In case of readahead, @I_LOCK flag is not
+ * ondemand_readahead -> readpage"). In case of readahead, @I_SYNC flag is not
  * set as well. However, UBIFS disables readahead.
  */
 
index 1d5b298..2259460 100644 (file)
@@ -794,7 +794,7 @@ xfs_setup_inode(
        struct inode            *inode = &ip->i_vnode;
 
        inode->i_ino = ip->i_ino;
-       inode->i_state = I_NEW|I_LOCK;
+       inode->i_state = I_NEW;
        inode_add_to_lists(ip->i_mount->m_super, inode);
 
        inode->i_mode   = ip->i_d.di_mode;
index 0de36c2..fa402a6 100644 (file)
@@ -91,7 +91,7 @@ xfs_inode_alloc(
        ip->i_new_size = 0;
 
        /* prevent anyone from using this yet */
-       VFS_I(ip)->i_state = I_NEW|I_LOCK;
+       VFS_I(ip)->i_state = I_NEW;
 
        return ip;
 }
@@ -217,7 +217,7 @@ xfs_iget_cache_hit(
                        trace_xfs_iget_reclaim(ip);
                        goto out_error;
                }
-               inode->i_state = I_LOCK|I_NEW;
+               inode->i_state = I_NEW;
        } else {
                /* If the VFS inode is being torn down, pause and try again. */
                if (!igrab(inode)) {
index 681ddf3..fcd268c 100644 (file)
@@ -51,7 +51,7 @@
 #endif
 
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
index f72914d..756f831 100644 (file)
@@ -118,6 +118,7 @@ header-y += mtio.h
 header-y += ncp_no.h
 header-y += neighbour.h
 header-y += net_dropmon.h
+header-y += net_tstamp.h
 header-y += netfilter_arp.h
 header-y += netrom.h
 header-y += nfs2.h
index 0f5f578..8c4f884 100644 (file)
@@ -36,18 +36,18 @@ struct backlight_device;
 struct fb_info;
 
 struct backlight_ops {
-       unsigned int options;
+       const unsigned int options;
 
 #define BL_CORE_SUSPENDRESUME  (1 << 0)
 
        /* Notify the backlight driver some property has changed */
-       int (*update_status)(struct backlight_device *);
+       int (* const update_status)(struct backlight_device *);
        /* Return the current backlight brightness (accounting for power,
           fb_blank etc.) */
-       int (*get_brightness)(struct backlight_device *);
+       int (* const get_brightness)(struct backlight_device *);
        /* Check if given framebuffer device is the one bound to this backlight;
           return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
-       int (*check_fb)(struct fb_info *);
+       int (* const check_fb)(struct fb_info *);
 };
 
 /* This structure defines all the properties of a backlight */
@@ -86,7 +86,7 @@ struct backlight_device {
           registered this device has been unloaded, and if class_get_devdata()
           points to something in the body of that driver, it is also invalid. */
        struct mutex ops_lock;
-       struct backlight_ops *ops;
+       const struct backlight_ops *ops;
 
        /* The framebuffer notifier block */
        struct notifier_block fb_notif;
@@ -103,7 +103,7 @@ static inline void backlight_update_status(struct backlight_device *bd)
 }
 
 extern struct backlight_device *backlight_device_register(const char *name,
-       struct device *dev, void *devdata, struct backlight_ops *ops);
+       struct device *dev, void *devdata, const struct backlight_ops *ops);
 extern void backlight_device_unregister(struct backlight_device *bd);
 extern void backlight_force_update(struct backlight_device *bd,
                                   enum backlight_update_reason reason);
index aece486..cd4349b 100644 (file)
@@ -68,6 +68,14 @@ struct linux_binprm{
 
 #define BINPRM_MAX_RECURSION 4
 
+/* Function parameter for binfmt->coredump */
+struct coredump_params {
+       long signr;
+       struct pt_regs *regs;
+       struct file *file;
+       unsigned long limit;
+};
+
 /*
  * This structure defines the functions that are used to load the binary formats that
  * linux accepts.
@@ -77,7 +85,7 @@ struct linux_binfmt {
        struct module *module;
        int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
        int (*load_shlib)(struct file *);
-       int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+       int (*core_dump)(struct coredump_params *cprm);
        unsigned long min_coredump;     /* minimal dump size */
        int hasvdso;
 };
index 90d1c21..9a33c5f 100644 (file)
@@ -42,6 +42,8 @@ enum enclosure_status {
        ENCLOSURE_STATUS_NOT_INSTALLED,
        ENCLOSURE_STATUS_UNKNOWN,
        ENCLOSURE_STATUS_UNAVAILABLE,
+       /* last element for counting purposes */
+       ENCLOSURE_STATUS_MAX
 };
 
 /* SFF-8485 activity light settings */
index 66bc0a5..cca1919 100644 (file)
@@ -1095,10 +1095,6 @@ struct file_lock {
 
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
-/* fs/sync.c */
-extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
-                       loff_t endbyte, unsigned int flags);
-
 #ifdef CONFIG_FILE_LOCKING
 extern int fcntl_getlk(struct file *, struct flock __user *);
 extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
@@ -1591,7 +1587,7 @@ struct super_operations {
  * until that flag is cleared.  I_WILL_FREE, I_FREEING and I_CLEAR are set at
  * various stages of removing an inode.
  *
- * Two bits are used for locking and completion notification, I_LOCK and I_SYNC.
+ * Two bits are used for locking and completion notification, I_NEW and I_SYNC.
  *
  * I_DIRTY_SYNC                Inode is dirty, but doesn't have to be written on
  *                     fdatasync().  i_atime is the usual cause.
@@ -1600,8 +1596,14 @@ struct super_operations {
  *                     don't have to write inode on fdatasync() when only
  *                     mtime has changed in it.
  * I_DIRTY_PAGES       Inode has dirty pages.  Inode itself may be clean.
- * I_NEW               get_new_inode() sets i_state to I_LOCK|I_NEW.  Both
- *                     are cleared by unlock_new_inode(), called from iget().
+ * I_NEW               Serves as both a mutex and completion notification.
+ *                     New inodes set I_NEW.  If two processes both create
+ *                     the same inode, one of them will release its inode and
+ *                     wait for I_NEW to be released before returning.
+ *                     Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
+ *                     also cause waiting on I_NEW, without I_NEW actually
+ *                     being set.  find_inode() uses this to prevent returning
+ *                     nearly-dead inodes.
  * I_WILL_FREE         Must be set when calling write_inode_now() if i_count
  *                     is zero.  I_FREEING must be set when I_WILL_FREE is
  *                     cleared.
@@ -1615,20 +1617,11 @@ struct super_operations {
  *                     prohibited for many purposes.  iget() must wait for
  *                     the inode to be completely released, then create it
  *                     anew.  Other functions will just ignore such inodes,
- *                     if appropriate.  I_LOCK is used for waiting.
+ *                     if appropriate.  I_NEW is used for waiting.
  *
- * I_LOCK              Serves as both a mutex and completion notification.
- *                     New inodes set I_LOCK.  If two processes both create
- *                     the same inode, one of them will release its inode and
- *                     wait for I_LOCK to be released before returning.
- *                     Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
- *                     also cause waiting on I_LOCK, without I_LOCK actually
- *                     being set.  find_inode() uses this to prevent returning
- *                     nearly-dead inodes.
- * I_SYNC              Similar to I_LOCK, but limited in scope to writeback
- *                     of inode dirty data.  Having a separate lock for this
- *                     purpose reduces latency and prevents some filesystem-
- *                     specific deadlocks.
+ * I_SYNC              Synchonized write of dirty inode data.  The bits is
+ *                     set during data writeback, and cleared with a wakeup
+ *                     on the bit address once it is done.
  *
  * Q: What is the difference between I_WILL_FREE and I_FREEING?
  * Q: igrab() only checks on (I_FREEING|I_WILL_FREE).  Should it also check on
@@ -1637,13 +1630,12 @@ struct super_operations {
 #define I_DIRTY_SYNC           1
 #define I_DIRTY_DATASYNC       2
 #define I_DIRTY_PAGES          4
-#define I_NEW                  8
+#define __I_NEW                        3
+#define I_NEW                  (1 << __I_NEW)
 #define I_WILL_FREE            16
 #define I_FREEING              32
 #define I_CLEAR                        64
-#define __I_LOCK               7
-#define I_LOCK                 (1 << __I_LOCK)
-#define __I_SYNC               8
+#define __I_SYNC               7
 #define I_SYNC                 (1 << __I_SYNC)
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
index bb516ce..da317c7 100644 (file)
@@ -8,10 +8,8 @@
 #include <linux/fs.h>
 
 /* externs for fs/stack.c */
-extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-                               int (*get_nlinks)(struct inode *));
-
-extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
+extern void fsstack_copy_inode_size(struct inode *dst, struct inode *src);
 
 /* inlines */
 static inline void fsstack_copy_attr_atime(struct inode *dest,
index 5ed8b9c..abec69b 100644 (file)
@@ -111,12 +111,6 @@ extern struct cred init_cred;
 # define INIT_PERF_EVENTS(tsk)
 #endif
 
-#ifdef CONFIG_FS_JOURNAL_INFO
-#define INIT_JOURNAL_INFO      .journal_info = NULL,
-#else
-#define INIT_JOURNAL_INFO
-#endif
-
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -168,6 +162,7 @@ extern struct cred init_cred;
                .signal = {{0}}},                                       \
        .blocked        = {{0}},                                        \
        .alloc_lock     = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),         \
+       .journal_info   = NULL,                                         \
        .cpu_timers     = INIT_CPU_TIMERS(tsk.cpu_timers),              \
        .fs_excl        = ATOMIC_INIT(0),                               \
        .pi_lock        = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),        \
@@ -178,7 +173,6 @@ extern struct cred init_cred;
                [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            \
        },                                                              \
        .dirties = INIT_PROP_LOCAL_SINGLE(dirties),                     \
-       INIT_JOURNAL_INFO                                               \
        INIT_IDS                                                        \
        INIT_PERF_EVENTS(tsk)                                           \
        INIT_TRACE_IRQFLAGS                                             \
index 3c7497d..99d9a67 100644 (file)
@@ -32,8 +32,7 @@ extern void kmemleak_padding(const void *ptr, unsigned long offset,
                             size_t size) __ref;
 extern void kmemleak_not_leak(const void *ptr) __ref;
 extern void kmemleak_ignore(const void *ptr) __ref;
-extern void kmemleak_scan_area(const void *ptr, unsigned long offset,
-                              size_t length, gfp_t gfp) __ref;
+extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref;
 extern void kmemleak_no_scan(const void *ptr) __ref;
 
 static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
@@ -84,8 +83,7 @@ static inline void kmemleak_not_leak(const void *ptr)
 static inline void kmemleak_ignore(const void *ptr)
 {
 }
-static inline void kmemleak_scan_area(const void *ptr, unsigned long offset,
-                                     size_t length, gfp_t gfp)
+static inline void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
 }
 static inline void kmemleak_erase(void **ptr)
index afc9f9f..2618aa9 100644 (file)
@@ -12,9 +12,6 @@
 #ifndef __LINUX_LEDS_LP3944_H
 #define __LINUX_LEDS_LP3944_H
 
-#include <linux/leds.h>
-#include <linux/workqueue.h>
-
 #define LP3944_LED0 0
 #define LP3944_LED1 1
 #define LP3944_LED2 2
index 96eea90..f158eb1 100644 (file)
@@ -32,7 +32,7 @@ struct pca9532_led {
        struct i2c_client *client;
        char *name;
        struct led_classdev ldev;
-       struct work_struct work;
+       struct work_struct work;
        enum pca9532_type type;
        enum pca9532_state state;
 };
diff --git a/include/linux/leds-regulator.h b/include/linux/leds-regulator.h
new file mode 100644 (file)
index 0000000..5a8eb38
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * leds-regulator.h - platform data structure for regulator driven LEDs.
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LINUX_LEDS_REGULATOR_H
+#define __LINUX_LEDS_REGULATOR_H
+
+/*
+ * Use "vled" as supply id when declaring the regulator consumer:
+ *
+ * static struct regulator_consumer_supply pcap_regulator_VVIB_consumers [] = {
+ *     { .dev_name = "leds-regulator.0", supply = "vled" },
+ * };
+ *
+ * If you have several regulator driven LEDs, you can append a numerical id to
+ * .dev_name as done above, and use the same id when declaring the platform
+ * device:
+ *
+ * static struct led_regulator_platform_data a780_vibrator_data = {
+ *     .name   = "a780::vibrator",
+ * };
+ *
+ * static struct platform_device a780_vibrator = {
+ *     .name = "leds-regulator",
+ *     .id   = 0,
+ *     .dev  = {
+ *             .platform_data = &a780_vibrator_data,
+ *     },
+ * };
+ */
+
+#include <linux/leds.h>
+
+struct led_regulator_platform_data {
+       char *name;                     /* LED name as expected by LED class */
+       enum led_brightness brightness; /* initial brightness value */
+};
+
+#endif /* __LINUX_LEDS_REGULATOR_H */
index 415c228..fd322ac 100644 (file)
@@ -41,6 +41,23 @@ struct wm831x_battery_pdata {
        int timeout;        /** Charge cycle timeout, in minutes */
 };
 
+/**
+ * Configuration for the WM831x DC-DC BuckWise convertors.  This
+ * should be passed as driver_data in the regulator_init_data.
+ *
+ * Currently all the configuration is for the fast DVS switching
+ * support of the devices.  This allows MFPs on the device to be
+ * configured as an input to switch between two output voltages,
+ * allowing voltage transitions without the expense of an access over
+ * I2C or SPI buses.
+ */
+struct wm831x_buckv_pdata {
+       int dvs_gpio;        /** CPU GPIO to use for DVS switching */
+       int dvs_control_src; /** Hardware DVS source to use (1 or 2) */
+       int dvs_init_state;  /** DVS state to expect on startup */
+       int dvs_state_gpio;  /** CPU GPIO to use for monitoring status */
+};
+
 /* Sources for status LED configuration.  Values are register values
  * plus 1 to allow for a zero default for preserve.
  */
index 8a55098..ee24ef8 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef LINUX_MM_DEBUG_H
 #define LINUX_MM_DEBUG_H 1
 
-#include <linux/autoconf.h>
-
 #ifdef CONFIG_DEBUG_VM
 #define VM_BUG_ON(cond) BUG_ON(cond)
 #else
index 6f75617..30fe668 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
-#include <linux/bounds.h>
+#include <generated/bounds.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
 
index d9ebf10..d74785c 100644 (file)
@@ -23,6 +23,7 @@ struct proc_mounts {
 
 struct fs_struct;
 
+extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt);
 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
                struct fs_struct *);
 extern void put_mnt_ns(struct mnt_namespace *ns);
index feee2ba..5b59f35 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/types.h>
 #ifndef __GENERATING_BOUNDS_H
 #include <linux/mm_types.h>
-#include <linux/bounds.h>
+#include <generated/bounds.h>
 #endif /* !__GENERATING_BOUNDS_H */
 
 /*
index 7a9754c..01b3d75 100644 (file)
@@ -10,7 +10,7 @@ struct platform_pwm_backlight_data {
        unsigned int dft_brightness;
        unsigned int pwm_period_ns;
        int (*init)(struct device *dev);
-       int (*notify)(int brightness);
+       int (*notify)(struct device *dev, int brightness);
        void (*exit)(struct device *dev);
 };
 
index 490c5b3..030d922 100644 (file)
@@ -35,6 +35,8 @@
 #ifndef __LINUX_REGULATOR_CONSUMER_H_
 #define __LINUX_REGULATOR_CONSUMER_H_
 
+#include <linux/device.h>
+
 /*
  * Regulator operating modes.
  *
index 87f5f17..234a847 100644 (file)
@@ -43,16 +43,20 @@ struct regulator;
 /**
  * struct regulator_state - regulator state during low power system states
  *
- * This describes a regulators state during a system wide low power state.
+ * This describes a regulators state during a system wide low power
+ * state.  One of enabled or disabled must be set for the
+ * configuration to be applied.
  *
  * @uV: Operating voltage during suspend.
  * @mode: Operating mode during suspend.
  * @enabled: Enabled during suspend.
+ * @disabled: Disabled during suspend.
  */
 struct regulator_state {
        int uV; /* suspend voltage */
        unsigned int mode; /* suspend regulator operating mode */
        int enabled; /* is regulator enabled in this suspend state */
+       int disabled; /* is the regulator disbled in this suspend state */
 };
 
 /**
diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h
new file mode 100644 (file)
index 0000000..9936763
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * max8660.h  --  Voltage regulation for the Maxim 8660/8661
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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 __LINUX_REGULATOR_MAX8660_H
+#define __LINUX_REGULATOR_MAX8660_H
+
+#include <linux/regulator/machine.h>
+
+enum {
+       MAX8660_V3,
+       MAX8660_V4,
+       MAX8660_V5,
+       MAX8660_V6,
+       MAX8660_V7,
+       MAX8660_V_END,
+};
+
+/**
+ * max8660_subdev_data - regulator subdev data
+ * @id: regulator id
+ * @name: regulator name
+ * @platform_data: regulator init data
+ */
+struct max8660_subdev_data {
+       int                             id;
+       char                            *name;
+       struct regulator_init_data      *platform_data;
+};
+
+/**
+ * max8660_platform_data - platform data for max8660
+ * @num_subdevs: number of regulators used
+ * @subdevs: pointer to regulators used
+ * @en34_is_high: if EN34 is driven high, regulators cannot be en-/disabled.
+ */
+struct max8660_platform_data {
+       int num_subdevs;
+       struct max8660_subdev_data *subdevs;
+       unsigned en34_is_high:1;
+};
+#endif
index 244c287..e898578 100644 (file)
@@ -1446,10 +1446,8 @@ struct task_struct {
        gfp_t lockdep_reclaim_gfp;
 #endif
 
-#ifdef CONFIG_FS_JOURNAL_INFO
 /* journalling filesystem info */
        void *journal_info;
-#endif
 
 /* stacked block device info */
        struct bio *bio_list, **bio_tail;
@@ -1555,7 +1553,7 @@ struct task_struct {
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
-#define tsk_cpumask(tsk) (&(tsk)->cpus_allowed)
+#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
 
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
index 466cbad..2c627d3 100644 (file)
@@ -95,8 +95,13 @@ struct seq_file;
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+#ifdef CONFIG_MMU
 extern unsigned long mmap_min_addr;
 extern unsigned long dac_mmap_min_addr;
+#else
+#define dac_mmap_min_addr      0UL
+#endif
+
 /*
  * Values used in the task_security_ops calls
  */
@@ -121,6 +126,7 @@ struct request_sock;
 #define LSM_UNSAFE_PTRACE      2
 #define LSM_UNSAFE_PTRACE_CAP  4
 
+#ifdef CONFIG_MMU
 /*
  * If a hint addr is less than mmap_min_addr change hint to be as
  * low as possible but still greater than mmap_min_addr
@@ -135,6 +141,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
 }
 extern int mmap_min_addr_handler(struct ctl_table *table, int write,
                                 void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
 
 #ifdef CONFIG_SECURITY
 
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
new file mode 100644 (file)
index 0000000..51b3e77
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef DW_SPI_HEADER_H
+#define DW_SPI_HEADER_H
+#include <linux/io.h>
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET                 0
+
+#define SPI_FRF_OFFSET                 4
+#define SPI_FRF_SPI                    0x0
+#define SPI_FRF_SSP                    0x1
+#define SPI_FRF_MICROWIRE              0x2
+#define SPI_FRF_RESV                   0x3
+
+#define SPI_MODE_OFFSET                        6
+#define SPI_SCPH_OFFSET                        6
+#define SPI_SCOL_OFFSET                        7
+#define SPI_TMOD_OFFSET                        8
+#define        SPI_TMOD_TR                     0x0             /* xmit & recv */
+#define SPI_TMOD_TO                    0x1             /* xmit only */
+#define SPI_TMOD_RO                    0x2             /* recv only */
+#define SPI_TMOD_EPROMREAD             0x3             /* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET               10
+#define SPI_SRL_OFFSET                 11
+#define SPI_CFS_OFFSET                 12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK                                0x7f            /* cover 7 bits */
+#define SR_BUSY                                (1 << 0)
+#define SR_TF_NOT_FULL                 (1 << 1)
+#define SR_TF_EMPT                     (1 << 2)
+#define SR_RF_NOT_EMPT                 (1 << 3)
+#define SR_RF_FULL                     (1 << 4)
+#define SR_TX_ERR                      (1 << 5)
+#define SR_DCOL                                (1 << 6)
+
+/* Bit fields in ISR, IMR, RISR, 7 bits */
+#define SPI_INT_TXEI                   (1 << 0)
+#define SPI_INT_TXOI                   (1 << 1)
+#define SPI_INT_RXUI                   (1 << 2)
+#define SPI_INT_RXOI                   (1 << 3)
+#define SPI_INT_RXFI                   (1 << 4)
+#define SPI_INT_MSTI                   (1 << 5)
+
+/* TX RX interrupt level threshhold, max can be 256 */
+#define SPI_INT_THRESHOLD              32
+
+enum dw_ssi_type {
+       SSI_MOTO_SPI = 0,
+       SSI_TI_SSP,
+       SSI_NS_MICROWIRE,
+};
+
+struct dw_spi_reg {
+       u32     ctrl0;
+       u32     ctrl1;
+       u32     ssienr;
+       u32     mwcr;
+       u32     ser;
+       u32     baudr;
+       u32     txfltr;
+       u32     rxfltr;
+       u32     txflr;
+       u32     rxflr;
+       u32     sr;
+       u32     imr;
+       u32     isr;
+       u32     risr;
+       u32     txoicr;
+       u32     rxoicr;
+       u32     rxuicr;
+       u32     msticr;
+       u32     icr;
+       u32     dmacr;
+       u32     dmatdlr;
+       u32     dmardlr;
+       u32     idr;
+       u32     version;
+       u32     dr;             /* Currently oper as 32 bits,
+                               though only low 16 bits matters */
+} __packed;
+
+struct dw_spi {
+       struct spi_master       *master;
+       struct spi_device       *cur_dev;
+       struct device           *parent_dev;
+       enum dw_ssi_type        type;
+
+       void __iomem            *regs;
+       unsigned long           paddr;
+       u32                     iolen;
+       int                     irq;
+       u32                     max_freq;       /* max bus freq supported */
+
+       u16                     bus_num;
+       u16                     num_cs;         /* supported slave numbers */
+
+       /* Driver message queue */
+       struct workqueue_struct *workqueue;
+       struct work_struct      pump_messages;
+       spinlock_t              lock;
+       struct list_head        queue;
+       int                     busy;
+       int                     run;
+
+       /* Message Transfer pump */
+       struct tasklet_struct   pump_transfers;
+
+       /* Current message transfer state info */
+       struct spi_message      *cur_msg;
+       struct spi_transfer     *cur_transfer;
+       struct chip_data        *cur_chip;
+       struct chip_data        *prev_chip;
+       size_t                  len;
+       void                    *tx;
+       void                    *tx_end;
+       void                    *rx;
+       void                    *rx_end;
+       int                     dma_mapped;
+       dma_addr_t              rx_dma;
+       dma_addr_t              tx_dma;
+       size_t                  rx_map_len;
+       size_t                  tx_map_len;
+       u8                      n_bytes;        /* current is a 1/2 bytes op */
+       u8                      max_bits_per_word;      /* maxim is 16b */
+       u32                     dma_width;
+       int                     cs_change;
+       int                     (*write)(struct dw_spi *dws);
+       int                     (*read)(struct dw_spi *dws);
+       irqreturn_t             (*transfer_handler)(struct dw_spi *dws);
+       void                    (*cs_control)(u32 command);
+
+       /* Dma info */
+       int                     dma_inited;
+       struct dma_chan         *txchan;
+       struct dma_chan         *rxchan;
+       int                     txdma_done;
+       int                     rxdma_done;
+       u64                     tx_param;
+       u64                     rx_param;
+       struct device           *dma_dev;
+       dma_addr_t              dma_addr;
+
+       /* Bus interface info */
+       void                    *priv;
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs;
+#endif
+};
+
+#define dw_readl(dw, name) \
+       __raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+       __raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+       __raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+       __raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+
+static inline void spi_enable_chip(struct dw_spi *dws, int enable)
+{
+       dw_writel(dws, ssienr, (enable ? 1 : 0));
+}
+
+static inline void spi_set_clk(struct dw_spi *dws, u16 div)
+{
+       dw_writel(dws, baudr, div);
+}
+
+static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+{
+       if (cs > dws->num_cs)
+               return;
+       dw_writel(dws, ser, 1 << cs);
+}
+
+/* Disable IRQ bits */
+static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
+{
+       u32 new_mask;
+
+       new_mask = dw_readl(dws, imr) & ~mask;
+       dw_writel(dws, imr, new_mask);
+}
+
+/* Enable IRQ bits */
+static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
+{
+       u32 new_mask;
+
+       new_mask = dw_readl(dws, imr) | mask;
+       dw_writel(dws, imr, new_mask);
+}
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the "controller_data" member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+       u8 poll_mode;   /* 0 for contoller polling mode */
+       u8 type;        /* SPI/SSP/Micrwire */
+       u8 enable_dma;
+       void (*cs_control)(u32 command);
+};
+
+extern int dw_spi_add_host(struct dw_spi *dws);
+extern void dw_spi_remove_host(struct dw_spi *dws);
+extern int dw_spi_suspend_host(struct dw_spi *dws);
+extern int dw_spi_resume_host(struct dw_spi *dws);
+#endif /* DW_SPI_HEADER_H */
index 79b9837..cf97b5b 100644 (file)
@@ -1,4 +1,4 @@
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/module.h>
 
 /* Simply sanity version stamp for modules. */
index 3fb9944..d5dd0bc 100644 (file)
@@ -84,6 +84,8 @@ struct vt_setactivate {
 
 #define VT_SETACTIVATE 0x560F  /* Activate and set the mode of a console */
 
+#ifdef __KERNEL__
+
 #ifdef CONFIG_VT_CONSOLE
 
 extern int vt_kmsg_redirect(int new);
@@ -97,6 +99,8 @@ static inline int vt_kmsg_redirect(int new)
 
 #endif
 
+#endif /* __KERNEL__ */
+
 #define vt_get_kmsg_redirect() vt_kmsg_redirect(-1)
 
 #endif /* _LINUX_VT_H */
index 705f01f..c18c008 100644 (file)
@@ -79,8 +79,7 @@ void wakeup_flusher_threads(long nr_pages);
 static inline void wait_on_inode(struct inode *inode)
 {
        might_sleep();
-       wait_on_bit(&inode->i_state, __I_LOCK, inode_wait,
-                                                       TASK_UNINTERRUPTIBLE);
+       wait_on_bit(&inode->i_state, __I_NEW, inode_wait, TASK_UNINTERRUPTIBLE);
 }
 static inline void inode_sync_wait(struct inode *inode)
 {
index 39d6d10..a8f3701 100644 (file)
@@ -142,6 +142,7 @@ struct osd_request {
        struct _osd_io_info {
                struct bio *bio;
                u64 total_bytes;
+               u64 residual;
                struct request *req;
                struct _osd_req_data_segment *last_seg;
                u8 *pad_buff;
@@ -150,12 +151,14 @@ struct osd_request {
        gfp_t alloc_flags;
        unsigned timeout;
        unsigned retries;
+       unsigned sense_len;
        u8 sense[OSD_MAX_SENSE_LEN];
        enum osd_attributes_mode attributes_mode;
 
        osd_req_done_fn *async_done;
        void *async_private;
        int async_error;
+       int req_errors;
 };
 
 static inline bool osd_req_is_ver1(struct osd_request *or)
@@ -297,8 +300,6 @@ enum osd_err_priority {
 };
 
 struct osd_sense_info {
-       u64 out_resid;          /* Zero on success otherwise out residual */
-       u64 in_resid;           /* Zero on success otherwise in residual */
        enum osd_err_priority osd_err_pri;
 
        int key;                /* one of enum scsi_sense_keys */
index 4a243df..0bf677a 100644 (file)
@@ -15,12 +15,8 @@ mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
 mounts-$(CONFIG_BLK_DEV_INITRD)        += do_mounts_initrd.o
 mounts-$(CONFIG_BLK_DEV_MD)    += do_mounts_md.o
 
-# files to be removed upon make clean
-clean-files := ../include/linux/compile.h
-
 # dependencies on generated files need to be listed explicitly
-
-$(obj)/version.o: include/linux/compile.h
+$(obj)/version.o: include/generated/compile.h
 
 # compile.h changes depending on hostname, generation number, etc,
 # so we regenerate it always.
@@ -30,7 +26,7 @@ $(obj)/version.o: include/linux/compile.h
        chk_compile.h = :
  quiet_chk_compile.h = echo '  CHK     $@'
 silent_chk_compile.h = :
-include/linux/compile.h: FORCE
+include/generated/compile.h: FORCE
        @$($(quiet)chk_compile.h)
        $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
        "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
index 52a8b98..adff586 100644 (file)
@@ -6,11 +6,11 @@
  *  May be freely distributed as part of Linux.
  */
 
-#include <linux/compile.h>
+#include <generated/compile.h>
 #include <linux/module.h>
 #include <linux/uts.h>
 #include <linux/utsname.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/version.h>
 
 #ifndef CONFIG_KALLSYMS
index 3c53013..98a51f2 100644 (file)
@@ -12,7 +12,7 @@
 
 void foo(void)
 {
-       /* The enum constants to put into include/linux/bounds.h */
+       /* The enum constants to put into include/generated/bounds.h */
        DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
        DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
        /* End of constants */
index 5962d7c..546774a 100644 (file)
@@ -68,10 +68,10 @@ static void __unhash_process(struct task_struct *p)
                detach_pid(p, PIDTYPE_SID);
 
                list_del_rcu(&p->tasks);
+               list_del_init(&p->sibling);
                __get_cpu_var(process_counts)--;
        }
        list_del_rcu(&p->thread_group);
-       list_del_init(&p->sibling);
 }
 
 /*
@@ -736,12 +736,9 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 /*
 * Any that need to be release_task'd are put on the @dead list.
  */
-static void reparent_thread(struct task_struct *father, struct task_struct *p,
+static void reparent_leader(struct task_struct *father, struct task_struct *p,
                                struct list_head *dead)
 {
-       if (p->pdeath_signal)
-               group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
-
        list_move_tail(&p->sibling, &p->real_parent->children);
 
        if (task_detached(p))
@@ -780,12 +777,18 @@ static void forget_original_parent(struct task_struct *father)
        reaper = find_new_reaper(father);
 
        list_for_each_entry_safe(p, n, &father->children, sibling) {
-               p->real_parent = reaper;
-               if (p->parent == father) {
-                       BUG_ON(task_ptrace(p));
-                       p->parent = p->real_parent;
-               }
-               reparent_thread(father, p, &dead_children);
+               struct task_struct *t = p;
+               do {
+                       t->real_parent = reaper;
+                       if (t->parent == father) {
+                               BUG_ON(task_ptrace(t));
+                               t->parent = t->real_parent;
+                       }
+                       if (t->pdeath_signal)
+                               group_send_sig_info(t->pdeath_signal,
+                                                   SEND_SIG_NOINFO, t);
+               } while_each_thread(p, t);
+               reparent_leader(father, p, &dead_children);
        }
        write_unlock_irq(&tasklist_lock);
 
@@ -1551,14 +1554,9 @@ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
        struct task_struct *p;
 
        list_for_each_entry(p, &tsk->children, sibling) {
-               /*
-                * Do not consider detached threads.
-                */
-               if (!task_detached(p)) {
-                       int ret = wait_consider_task(wo, 0, p);
-                       if (ret)
-                               return ret;
-               }
+               int ret = wait_consider_task(wo, 0, p);
+               if (ret)
+                       return ret;
        }
 
        return 0;
index 202a0ba..5b2959b 100644 (file)
@@ -1291,7 +1291,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        }
 
        if (likely(p->pid)) {
-               list_add_tail(&p->sibling, &p->real_parent->children);
                tracehook_finish_clone(p, clone_flags, trace);
 
                if (thread_group_leader(p)) {
@@ -1303,6 +1302,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                        p->signal->tty = tty_kref_get(current->signal->tty);
                        attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
                        attach_pid(p, PIDTYPE_SID, task_session(current));
+                       list_add_tail(&p->sibling, &p->real_parent->children);
                        list_add_tail_rcu(&p->tasks, &init_task.tasks);
                        __get_cpu_var(process_counts)++;
                }
index 433e9fc..a9a93d9 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/hardirq.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/numa.h>
 #include <linux/suspend.h>
index a65dc78..e96b8ed 100644 (file)
@@ -1910,9 +1910,7 @@ static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
        unsigned int i;
 
        /* only scan the sections containing data */
-       kmemleak_scan_area(mod->module_core, (unsigned long)mod -
-                          (unsigned long)mod->module_core,
-                          sizeof(struct module), GFP_KERNEL);
+       kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL);
 
        for (i = 1; i < hdr->e_shnum; i++) {
                if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -1921,8 +1919,7 @@ static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr,
                    && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0)
                        continue;
 
-               kmemleak_scan_area(mod->module_core, sechdrs[i].sh_addr -
-                                  (unsigned long)mod->module_core,
+               kmemleak_scan_area((void *)sechdrs[i].sh_addr,
                                   sechdrs[i].sh_size, GFP_KERNEL);
        }
 }
@@ -2250,6 +2247,12 @@ static noinline struct module *load_module(void __user *umod,
                                         "_ftrace_events",
                                         sizeof(*mod->trace_events),
                                         &mod->num_trace_events);
+       /*
+        * This section contains pointers to allocated objects in the trace
+        * code and not scanning it leads to false positives.
+        */
+       kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) *
+                          mod->num_trace_events, GFP_KERNEL);
 #endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
        /* sechdrs[0].sh_size is always zero */
index 8ab8698..97d1a3d 100644 (file)
@@ -1614,7 +1614,7 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu)
                 * offline CPU and activate it when the CPU comes up, but
                 * that's for later.
                 */
-               if (!cpu_isset(cpu, cpu_online_map))
+               if (!cpu_online(cpu))
                        return ERR_PTR(-ENODEV);
 
                cpuctx = &per_cpu(perf_cpu_context, cpu);
index 1ded8e7..17463ca 100644 (file)
@@ -1412,7 +1412,7 @@ static LIST_HEAD(dump_list);
 
 /**
  * kmsg_dump_register - register a kernel log dumper.
- * @dump: pointer to the kmsg_dumper structure
+ * @dumper: pointer to the kmsg_dumper structure
  *
  * Adds a kernel log dumper to the system. The dump callback in the
  * structure will be called when the kernel oopses or panics and must be
@@ -1442,7 +1442,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_register);
 
 /**
  * kmsg_dump_unregister - unregister a kmsg dumper.
- * @dump: pointer to the kmsg_dumper structure
+ * @dumper: pointer to the kmsg_dumper structure
  *
  * Removes a dump device from the system. Returns zero on success and
  * %-EINVAL otherwise.
index 45e4bef..8a68b24 100644 (file)
@@ -1131,7 +1131,7 @@ static struct ctl_table vm_table[] = {
                .data           = &sysctl_max_map_count,
                .maxlen         = sizeof(sysctl_max_map_count),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
                .extra1         = &zero,
        },
 #else
@@ -1214,6 +1214,7 @@ static struct ctl_table vm_table[] = {
                .proc_handler   = proc_dointvec_jiffies,
        },
 #endif
+#ifdef CONFIG_MMU
        {
                .procname       = "mmap_min_addr",
                .data           = &dac_mmap_min_addr,
@@ -1221,6 +1222,7 @@ static struct ctl_table vm_table[] = {
                .mode           = 0644,
                .proc_handler   = mmap_min_addr_handler,
        },
+#endif
 #ifdef CONFIG_NUMA
        {
                .procname       = "numa_zonelist_order",
index 2826563..bdfb8dd 100644 (file)
@@ -237,10 +237,10 @@ static void timer_list_show_tickdevices(struct seq_file *m)
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
        print_tickdevice(m, tick_get_broadcast_device(), -1);
        SEQ_printf(m, "tick_broadcast_mask: %08lx\n",
-                  tick_get_broadcast_mask()->bits[0]);
+                  cpumask_bits(tick_get_broadcast_mask())[0]);
 #ifdef CONFIG_TICK_ONESHOT
        SEQ_printf(m, "tick_broadcast_oneshot_mask: %08lx\n",
-                  tick_get_broadcast_oneshot_mask()->bits[0]);
+                  cpumask_bits(tick_get_broadcast_oneshot_mask())[0]);
 #endif
        SEQ_printf(m, "\n");
 #endif
index 06ba267..8b9f20a 100644 (file)
@@ -12,7 +12,7 @@
  *  Copyright (C) 2004 William Lee Irwin III
  */
 #include <linux/ring_buffer.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/stacktrace.h>
 #include <linux/writeback.h>
 #include <linux/kallsyms.h>
index 8cf9938..25c3ed5 100644 (file)
@@ -360,6 +360,7 @@ config DEBUG_KMEMLEAK
        select DEBUG_FS if SYSFS
        select STACKTRACE if STACKTRACE_SUPPORT
        select KALLSYMS
+       select CRC32
        help
          Say Y here if you want to enable the memory leak
          detector. The memory allocation/freeing is traced in a way
index 735343f..d4996cf 100644 (file)
@@ -1179,7 +1179,18 @@ qualifier:
  * %ps output the name of a text symbol without offset
  * %pF output the name of a function pointer with its offset
  * %pf output the name of a function pointer without its offset
- * %pR output the address range in a struct resource
+ * %pR output the address range in a struct resource with decoded flags
+ * %pr output the address range in a struct resource with raw flags
+ * %pM output a 6-byte MAC address with colons
+ * %pm output a 6-byte MAC address without colons
+ * %pI4 print an IPv4 address without leading zeros
+ * %pi4 print an IPv4 address with leading zeros
+ * %pI6 print an IPv6 address with colons
+ * %pi6 print an IPv6 address without colons
+ * %pI6c print an IPv6 address as specified by
+ *   http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
+ *   case.
  * %n is ignored
  *
  * The return value is the number of characters which would
index 43ea8c3..ee9f3e0 100644 (file)
@@ -221,6 +221,7 @@ config KSM
 
 config DEFAULT_MMAP_MIN_ADDR
         int "Low address space to protect from user allocation"
+       depends on MMU
         default 4096
         help
          This is the portion of low virtual memory which should be protected
index 13f33b3..5b069e4 100644 (file)
@@ -93,6 +93,7 @@
 #include <linux/nodemask.h>
 #include <linux/mm.h>
 #include <linux/workqueue.h>
+#include <linux/crc32.h>
 
 #include <asm/sections.h>
 #include <asm/processor.h>
 #define MSECS_MIN_AGE          5000    /* minimum object age for reporting */
 #define SECS_FIRST_SCAN                60      /* delay before the first scan */
 #define SECS_SCAN_WAIT         600     /* subsequent auto scanning delay */
-#define GRAY_LIST_PASSES       25      /* maximum number of gray list scans */
 #define MAX_SCAN_SIZE          4096    /* maximum size of a scanned block */
 
 #define BYTES_PER_POINTER      sizeof(void *)
 /* scanning area inside a memory block */
 struct kmemleak_scan_area {
        struct hlist_node node;
-       unsigned long offset;
-       size_t length;
+       unsigned long start;
+       size_t size;
 };
 
 #define KMEMLEAK_GREY  0
@@ -149,6 +149,8 @@ struct kmemleak_object {
        int min_count;
        /* the total number of pointers found pointing to this object */
        int count;
+       /* checksum for detecting modified objects */
+       u32 checksum;
        /* memory ranges to be scanned inside an object (empty for all) */
        struct hlist_head area_list;
        unsigned long trace[MAX_TRACE];
@@ -164,8 +166,6 @@ struct kmemleak_object {
 #define OBJECT_REPORTED                (1 << 1)
 /* flag set to not scan the object */
 #define OBJECT_NO_SCAN         (1 << 2)
-/* flag set on newly allocated objects */
-#define OBJECT_NEW             (1 << 3)
 
 /* number of bytes to print per line; must be 16 or 32 */
 #define HEX_ROW_SIZE           16
@@ -241,8 +241,6 @@ struct early_log {
        const void *ptr;                /* allocated/freed memory block */
        size_t size;                    /* memory block size */
        int min_count;                  /* minimum reference count */
-       unsigned long offset;           /* scan area offset */
-       size_t length;                  /* scan area length */
        unsigned long trace[MAX_TRACE]; /* stack trace */
        unsigned int trace_len;         /* stack trace length */
 };
@@ -323,11 +321,6 @@ static bool color_gray(const struct kmemleak_object *object)
                object->count >= object->min_count;
 }
 
-static bool color_black(const struct kmemleak_object *object)
-{
-       return object->min_count == KMEMLEAK_BLACK;
-}
-
 /*
  * Objects are considered unreferenced only if their color is white, they have
  * not be deleted and have a minimum age to avoid false positives caused by
@@ -335,7 +328,7 @@ static bool color_black(const struct kmemleak_object *object)
  */
 static bool unreferenced_object(struct kmemleak_object *object)
 {
-       return (object->flags & OBJECT_ALLOCATED) && color_white(object) &&
+       return (color_white(object) && object->flags & OBJECT_ALLOCATED) &&
                time_before_eq(object->jiffies + jiffies_min_age,
                               jiffies_last_scan);
 }
@@ -348,11 +341,13 @@ static void print_unreferenced(struct seq_file *seq,
                               struct kmemleak_object *object)
 {
        int i;
+       unsigned int msecs_age = jiffies_to_msecs(jiffies - object->jiffies);
 
        seq_printf(seq, "unreferenced object 0x%08lx (size %zu):\n",
                   object->pointer, object->size);
-       seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
-                  object->comm, object->pid, object->jiffies);
+       seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu (age %d.%03ds)\n",
+                  object->comm, object->pid, object->jiffies,
+                  msecs_age / 1000, msecs_age % 1000);
        hex_dump_object(seq, object);
        seq_printf(seq, "  backtrace:\n");
 
@@ -381,6 +376,7 @@ static void dump_object_info(struct kmemleak_object *object)
        pr_notice("  min_count = %d\n", object->min_count);
        pr_notice("  count = %d\n", object->count);
        pr_notice("  flags = 0x%lx\n", object->flags);
+       pr_notice("  checksum = %d\n", object->checksum);
        pr_notice("  backtrace:\n");
        print_stack_trace(&trace, 4);
 }
@@ -522,12 +518,13 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
        INIT_HLIST_HEAD(&object->area_list);
        spin_lock_init(&object->lock);
        atomic_set(&object->use_count, 1);
-       object->flags = OBJECT_ALLOCATED | OBJECT_NEW;
+       object->flags = OBJECT_ALLOCATED;
        object->pointer = ptr;
        object->size = size;
        object->min_count = min_count;
-       object->count = -1;                     /* no color initially */
+       object->count = 0;                      /* white color initially */
        object->jiffies = jiffies;
+       object->checksum = 0;
 
        /* task information */
        if (in_irq()) {
@@ -720,14 +717,13 @@ static void make_black_object(unsigned long ptr)
  * Add a scanning area to the object. If at least one such area is added,
  * kmemleak will only scan these ranges rather than the whole memory block.
  */
-static void add_scan_area(unsigned long ptr, unsigned long offset,
-                         size_t length, gfp_t gfp)
+static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
 {
        unsigned long flags;
        struct kmemleak_object *object;
        struct kmemleak_scan_area *area;
 
-       object = find_and_get_object(ptr, 0);
+       object = find_and_get_object(ptr, 1);
        if (!object) {
                kmemleak_warn("Adding scan area to unknown object at 0x%08lx\n",
                              ptr);
@@ -741,7 +737,7 @@ static void add_scan_area(unsigned long ptr, unsigned long offset,
        }
 
        spin_lock_irqsave(&object->lock, flags);
-       if (offset + length > object->size) {
+       if (ptr + size > object->pointer + object->size) {
                kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
                dump_object_info(object);
                kmem_cache_free(scan_area_cache, area);
@@ -749,8 +745,8 @@ static void add_scan_area(unsigned long ptr, unsigned long offset,
        }
 
        INIT_HLIST_NODE(&area->node);
-       area->offset = offset;
-       area->length = length;
+       area->start = ptr;
+       area->size = size;
 
        hlist_add_head(&area->node, &object->area_list);
 out_unlock:
@@ -786,7 +782,7 @@ static void object_no_scan(unsigned long ptr)
  * processed later once kmemleak is fully initialized.
  */
 static void __init log_early(int op_type, const void *ptr, size_t size,
-                            int min_count, unsigned long offset, size_t length)
+                            int min_count)
 {
        unsigned long flags;
        struct early_log *log;
@@ -808,8 +804,6 @@ static void __init log_early(int op_type, const void *ptr, size_t size,
        log->ptr = ptr;
        log->size = size;
        log->min_count = min_count;
-       log->offset = offset;
-       log->length = length;
        if (op_type == KMEMLEAK_ALLOC)
                log->trace_len = __save_stack_trace(log->trace);
        crt_early_log++;
@@ -858,7 +852,7 @@ void __ref kmemleak_alloc(const void *ptr, size_t size, int min_count,
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                create_object((unsigned long)ptr, size, min_count, gfp);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_ALLOC, ptr, size, min_count, 0, 0);
+               log_early(KMEMLEAK_ALLOC, ptr, size, min_count);
 }
 EXPORT_SYMBOL_GPL(kmemleak_alloc);
 
@@ -873,7 +867,7 @@ void __ref kmemleak_free(const void *ptr)
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                delete_object_full((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0);
+               log_early(KMEMLEAK_FREE, ptr, 0, 0);
 }
 EXPORT_SYMBOL_GPL(kmemleak_free);
 
@@ -888,7 +882,7 @@ void __ref kmemleak_free_part(const void *ptr, size_t size)
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                delete_object_part((unsigned long)ptr, size);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_FREE_PART, ptr, size, 0, 0, 0);
+               log_early(KMEMLEAK_FREE_PART, ptr, size, 0);
 }
 EXPORT_SYMBOL_GPL(kmemleak_free_part);
 
@@ -903,7 +897,7 @@ void __ref kmemleak_not_leak(const void *ptr)
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                make_gray_object((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_NOT_LEAK, ptr, 0, 0, 0, 0);
+               log_early(KMEMLEAK_NOT_LEAK, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_not_leak);
 
@@ -919,22 +913,21 @@ void __ref kmemleak_ignore(const void *ptr)
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                make_black_object((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_IGNORE, ptr, 0, 0, 0, 0);
+               log_early(KMEMLEAK_IGNORE, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_ignore);
 
 /*
  * Limit the range to be scanned in an allocated memory block.
  */
-void __ref kmemleak_scan_area(const void *ptr, unsigned long offset,
-                             size_t length, gfp_t gfp)
+void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
        pr_debug("%s(0x%p)\n", __func__, ptr);
 
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
-               add_scan_area((unsigned long)ptr, offset, length, gfp);
+               add_scan_area((unsigned long)ptr, size, gfp);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_SCAN_AREA, ptr, 0, 0, offset, length);
+               log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
 }
 EXPORT_SYMBOL(kmemleak_scan_area);
 
@@ -948,11 +941,25 @@ void __ref kmemleak_no_scan(const void *ptr)
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
                object_no_scan((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
-               log_early(KMEMLEAK_NO_SCAN, ptr, 0, 0, 0, 0);
+               log_early(KMEMLEAK_NO_SCAN, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_no_scan);
 
 /*
+ * Update an object's checksum and return true if it was modified.
+ */
+static bool update_checksum(struct kmemleak_object *object)
+{
+       u32 old_csum = object->checksum;
+
+       if (!kmemcheck_is_obj_initialized(object->pointer, object->size))
+               return false;
+
+       object->checksum = crc32(0, (void *)object->pointer, object->size);
+       return object->checksum != old_csum;
+}
+
+/*
  * Memory scanning is a long process and it needs to be interruptable. This
  * function checks whether such interrupt condition occured.
  */
@@ -1031,11 +1038,14 @@ static void scan_block(void *_start, void *_end,
                 * added to the gray_list.
                 */
                object->count++;
-               if (color_gray(object))
+               if (color_gray(object)) {
                        list_add_tail(&object->gray_list, &gray_list);
-               else
-                       put_object(object);
+                       spin_unlock_irqrestore(&object->lock, flags);
+                       continue;
+               }
+
                spin_unlock_irqrestore(&object->lock, flags);
+               put_object(object);
        }
 }
 
@@ -1075,14 +1085,47 @@ static void scan_object(struct kmemleak_object *object)
                }
        } else
                hlist_for_each_entry(area, elem, &object->area_list, node)
-                       scan_block((void *)(object->pointer + area->offset),
-                                  (void *)(object->pointer + area->offset
-                                           + area->length), object, 0);
+                       scan_block((void *)area->start,
+                                  (void *)(area->start + area->size),
+                                  object, 0);
 out:
        spin_unlock_irqrestore(&object->lock, flags);
 }
 
 /*
+ * Scan the objects already referenced (gray objects). More objects will be
+ * referenced and, if there are no memory leaks, all the objects are scanned.
+ */
+static void scan_gray_list(void)
+{
+       struct kmemleak_object *object, *tmp;
+
+       /*
+        * The list traversal is safe for both tail additions and removals
+        * from inside the loop. The kmemleak objects cannot be freed from
+        * outside the loop because their use_count was incremented.
+        */
+       object = list_entry(gray_list.next, typeof(*object), gray_list);
+       while (&object->gray_list != &gray_list) {
+               cond_resched();
+
+               /* may add new objects to the list */
+               if (!scan_should_stop())
+                       scan_object(object);
+
+               tmp = list_entry(object->gray_list.next, typeof(*object),
+                                gray_list);
+
+               /* remove the object from the list and release it */
+               list_del(&object->gray_list);
+               put_object(object);
+
+               object = tmp;
+       }
+       WARN_ON(!list_empty(&gray_list));
+}
+
+/*
  * Scan data sections and all the referenced memory blocks allocated via the
  * kernel's standard allocators. This function must be called with the
  * scan_mutex held.
@@ -1090,10 +1133,9 @@ out:
 static void kmemleak_scan(void)
 {
        unsigned long flags;
-       struct kmemleak_object *object, *tmp;
+       struct kmemleak_object *object;
        int i;
        int new_leaks = 0;
-       int gray_list_pass = 0;
 
        jiffies_last_scan = jiffies;
 
@@ -1114,7 +1156,6 @@ static void kmemleak_scan(void)
 #endif
                /* reset the reference count (whiten the object) */
                object->count = 0;
-               object->flags &= ~OBJECT_NEW;
                if (color_gray(object) && get_object(object))
                        list_add_tail(&object->gray_list, &gray_list);
 
@@ -1172,62 +1213,36 @@ static void kmemleak_scan(void)
 
        /*
         * Scan the objects already referenced from the sections scanned
-        * above. More objects will be referenced and, if there are no memory
-        * leaks, all the objects will be scanned. The list traversal is safe
-        * for both tail additions and removals from inside the loop. The
-        * kmemleak objects cannot be freed from outside the loop because their
-        * use_count was increased.
+        * above.
         */
-repeat:
-       object = list_entry(gray_list.next, typeof(*object), gray_list);
-       while (&object->gray_list != &gray_list) {
-               cond_resched();
-
-               /* may add new objects to the list */
-               if (!scan_should_stop())
-                       scan_object(object);
-
-               tmp = list_entry(object->gray_list.next, typeof(*object),
-                                gray_list);
-
-               /* remove the object from the list and release it */
-               list_del(&object->gray_list);
-               put_object(object);
-
-               object = tmp;
-       }
-
-       if (scan_should_stop() || ++gray_list_pass >= GRAY_LIST_PASSES)
-               goto scan_end;
+       scan_gray_list();
 
        /*
-        * Check for new objects allocated during this scanning and add them
-        * to the gray list.
+        * Check for new or unreferenced objects modified since the previous
+        * scan and color them gray until the next scan.
         */
        rcu_read_lock();
        list_for_each_entry_rcu(object, &object_list, object_list) {
                spin_lock_irqsave(&object->lock, flags);
-               if ((object->flags & OBJECT_NEW) && !color_black(object) &&
-                   get_object(object)) {
-                       object->flags &= ~OBJECT_NEW;
+               if (color_white(object) && (object->flags & OBJECT_ALLOCATED)
+                   && update_checksum(object) && get_object(object)) {
+                       /* color it gray temporarily */
+                       object->count = object->min_count;
                        list_add_tail(&object->gray_list, &gray_list);
                }
                spin_unlock_irqrestore(&object->lock, flags);
        }
        rcu_read_unlock();
 
-       if (!list_empty(&gray_list))
-               goto repeat;
-
-scan_end:
-       WARN_ON(!list_empty(&gray_list));
+       /*
+        * Re-scan the gray list for modified unreferenced objects.
+        */
+       scan_gray_list();
 
        /*
-        * If scanning was stopped or new objects were being allocated at a
-        * higher rate than gray list scanning, do not report any new
-        * unreferenced objects.
+        * If scanning was stopped do not report any new unreferenced objects.
         */
-       if (scan_should_stop() || gray_list_pass >= GRAY_LIST_PASSES)
+       if (scan_should_stop())
                return;
 
        /*
@@ -1642,8 +1657,7 @@ void __init kmemleak_init(void)
                        kmemleak_ignore(log->ptr);
                        break;
                case KMEMLEAK_SCAN_AREA:
-                       kmemleak_scan_area(log->ptr, log->offset, log->length,
-                                          GFP_KERNEL);
+                       kmemleak_scan_area(log->ptr, log->size, GFP_KERNEL);
                        break;
                case KMEMLEAK_NO_SCAN:
                        kmemleak_no_scan(log->ptr);
index aa1aa23..033bc13 100644 (file)
@@ -547,5 +547,17 @@ page_cache_async_readahead(struct address_space *mapping,
 
        /* do read-ahead */
        ondemand_readahead(mapping, ra, filp, true, offset, req_size);
+
+#ifdef CONFIG_BLOCK
+       /*
+        * Normally the current page is !uptodate and lock_page() will be
+        * immediately called to implicitly unplug the device. However this
+        * is not always true for RAID conifgurations, where data arrives
+        * not strictly in their submission order. In this case we need to
+        * explicitly kick off the IO.
+        */
+       if (PageUptodate(page))
+               blk_run_backing_dev(mapping->backing_dev_info, NULL);
+#endif
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
index 3f48229..7d41f15 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1132,7 +1132,7 @@ static void __cpuinit cpuup_canceled(long cpu)
                if (nc)
                        free_block(cachep, nc->entry, nc->avail, node);
 
-               if (!cpus_empty(*mask)) {
+               if (!cpumask_empty(mask)) {
                        spin_unlock_irq(&l3->list_lock);
                        goto free_array_cache;
                }
@@ -2275,9 +2275,11 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        /*
         * Determine if the slab management is 'on' or 'off' slab.
         * (bootstrapping cannot cope with offslab caches so don't do
-        * it too early on.)
+        * it too early on. Always use on-slab management when
+        * SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
         */
-       if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)
+       if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
+           !(flags & SLAB_NOLEAKTRACE))
                /*
                 * Size is large, assume best to place the slab management obj
                 * off-slab (should allow better packing of objs).
@@ -2596,8 +2598,8 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
                 * kmemleak does not treat the ->s_mem pointer as a reference
                 * to the object. Otherwise we will not report the leak.
                 */
-               kmemleak_scan_area(slabp, offsetof(struct slab, list),
-                                  sizeof(struct list_head), local_flags);
+               kmemleak_scan_area(&slabp->list, sizeof(struct list_head),
+                                  local_flags);
                if (!slabp)
                        return NULL;
        } else {
index dbfdfa9..769c386 100644 (file)
@@ -312,18 +312,6 @@ static struct file_system_type sock_fs_type = {
        .kill_sb =      kill_anon_super,
 };
 
-static int sockfs_delete_dentry(struct dentry *dentry)
-{
-       /*
-        * At creation time, we pretended this dentry was hashed
-        * (by clearing DCACHE_UNHASHED bit in d_flags)
-        * At delete time, we restore the truth : not hashed.
-        * (so that dput() can proceed correctly)
-        */
-       dentry->d_flags |= DCACHE_UNHASHED;
-       return 0;
-}
-
 /*
  * sockfs_dname() is called from d_path().
  */
@@ -334,7 +322,6 @@ static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
 }
 
 static const struct dentry_operations sockfs_dentry_operations = {
-       .d_delete = sockfs_delete_dentry,
        .d_dname  = sockfs_dname,
 };
 
@@ -374,12 +361,6 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
        path.mnt = mntget(sock_mnt);
 
        path.dentry->d_op = &sockfs_dentry_operations;
-       /*
-        * We dont want to push this dentry into global dentry hash table.
-        * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
-        * This permits a working /proc/$pid/fd/XXX on sockets
-        */
-       path.dentry->d_flags &= ~DCACHE_UNHASHED;
        d_instantiate(path.dentry, SOCK_INODE(sock));
        SOCK_INODE(sock)->i_fop = &socket_file_ops;
 
index c67e73e..ed2773e 100644 (file)
@@ -149,6 +149,12 @@ ld-option = $(call try-run,\
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
+# Usage:
+# $(Q)$(MAKE) $(modbuiltin)=dir
+modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
+
 # Prefix -I with $(srctree) if it is not an absolute path.
 # skip if -I has no parameter
 addtree = $(if $(patsubst -I%,%,$(1)), \
index 341b589..0b94d2f 100644 (file)
@@ -207,6 +207,7 @@ endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
 cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+       "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
        "$(if $(CONFIG_64BIT),64,32)" \
        "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
        "$(if $(part-of-module),1,0)" "$(@)";
index 224d85e..cd815ac 100644 (file)
@@ -213,7 +213,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -f -9 > $@) || \
 
 # Bzip2 and LZMA do not include size in file... so we have to fake that;
 # append the size as a 32-bit littleendian number as gzip does.
-size_append = /bin/echo -ne $(shell                                    \
+size_append = printf $(shell                                           \
 dec_size=0;                                                            \
 for F in $1; do                                                                \
        fsize=$$(stat -c "%s" $$F);                                     \
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
new file mode 100644 (file)
index 0000000..102a276
--- /dev/null
@@ -0,0 +1,55 @@
+# ==========================================================================
+# Generating modules.builtin
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __modbuiltin
+__modbuiltin:
+
+-include include/config/auto.conf
+# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
+# That way, we get the list of built-in modules in obj-Y
+-include include/config/tristate.conf
+
+include scripts/Kbuild.include
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
+include $(kbuild-file)
+
+include scripts/Makefile.lib
+__subdir-Y     := $(patsubst %/,%,$(filter %/, $(obj-Y)))
+subdir-Y       += $(__subdir-Y)
+subdir-ym      := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
+subdir-ym      := $(addprefix $(obj)/,$(subdir-ym))
+obj-Y          := $(addprefix $(obj)/,$(obj-Y))
+
+modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym))
+modbuiltin-mods    := $(filter %.ko, $(obj-Y:.o=.ko))
+modbuiltin-target  := $(obj)/modules.builtin
+
+__modbuiltin: $(modbuiltin-target) $(subdir-ym)
+       @:
+
+$(modbuiltin-target): $(subdir-ym) FORCE
+       $(Q)(for m in $(modbuiltin-mods); do echo kernel/$$m; done;     \
+       cat /dev/null $(modbuiltin-subdirs)) > $@
+
+PHONY += FORCE
+
+FORCE:
+
+# Descending
+# ---------------------------------------------------------------------------
+
+PHONY += $(subdir-ym)
+$(subdir-ym):
+       $(Q)$(MAKE) $(modbuiltin)=$@
+
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
index 6bf21f8..ea26b23 100644 (file)
  * tells make when to remake a file.
  *
  * To use this list as-is however has the drawback that virtually
- * every file in the kernel includes <linux/autoconf.h>.
+ * every file in the kernel includes autoconf.h.
  *
- * If the user re-runs make *config, linux/autoconf.h will be
+ * If the user re-runs make *config, autoconf.h will be
  * regenerated.  make notices that and will rebuild every file which
  * includes autoconf.h, i.e. basically all files. This is extremely
  * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
  *
  * So we play the same trick that "mkdep" played before. We replace
- * the dependency on linux/autoconf.h by a dependency on every config
+ * the dependency on autoconf.h by a dependency on every config
  * option which is mentioned in any of the listed prequisites.
  *
  * kconfig populates a tree in include/config/ with an empty file
@@ -73,7 +73,7 @@
  *   cmd_<target> = <cmdline>
  *
  * and then basically copies the .<target>.d file to stdout, in the
- * process filtering out the dependency on linux/autoconf.h and adding
+ * process filtering out the dependency on autoconf.h and adding
  * dependencies on include/config/my/option.h for every
  * CONFIG_MY_OPTION encountered in any of the prequisites.
  *
@@ -324,7 +324,7 @@ static void parse_dep_file(void *map, size_t len)
                        p++;
                }
                memcpy(s, m, p-m); s[p-m] = 0;
-               if (strrcmp(s, "include/linux/autoconf.h") &&
+               if (strrcmp(s, "include/generated/autoconf.h") &&
                    strrcmp(s, "arch/um/include/uml-config.h") &&
                    strrcmp(s, ".ver")) {
                        printf("  %s \\\n", s);
index 287467a..8060e06 100644 (file)
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.3 */
+/* ANSI-C code produced by gperf version 3.0.4 */
 /* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf  */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -34,7 +34,7 @@ struct resword;
 static const struct resword *is_reserved_word(register const char *str, register unsigned int len);
 #line 5 "scripts/genksyms/keywords.gperf"
 struct resword { const char *name; int token; };
-/* maximum key range = 62, duplicates = 0 */
+/* maximum key range = 64, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -48,39 +48,39 @@ is_reserved_hash (register const char *str, register unsigned int len)
 {
   static const unsigned char asso_values[] =
     {
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65,  5,
-      65, 65, 65, 65, 65, 65, 35, 65, 65, 65,
-       0, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65,  0, 65,  0, 65,  5,
-      20, 15, 10, 30, 65, 15, 65, 65, 20,  0,
-      10, 35, 20, 65, 10,  5,  0, 10,  5, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67,  0,
+      67, 67, 67, 67, 67, 67, 15, 67, 67, 67,
+       0, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67,  0, 67,  0, 67,  5,
+      25, 20, 15, 30, 67, 15, 67, 67, 10,  0,
+      10, 40, 20, 67, 10,  5,  0, 10, 15, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67
     };
   return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
 }
 
 #ifdef __GNUC__
 __inline
-#ifdef __GNUC_STDC_INLINE__
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
@@ -89,116 +89,119 @@ is_reserved_word (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 43,
+      TOTAL_KEYWORDS = 45,
       MIN_WORD_LENGTH = 3,
       MAX_WORD_LENGTH = 24,
       MIN_HASH_VALUE = 3,
-      MAX_HASH_VALUE = 64
+      MAX_HASH_VALUE = 66
     };
 
   static const struct resword wordlist[] =
     {
       {""}, {""}, {""},
-#line 28 "scripts/genksyms/keywords.gperf"
+#line 30 "scripts/genksyms/keywords.gperf"
       {"asm", ASM_KEYW},
       {""},
-#line 10 "scripts/genksyms/keywords.gperf"
+#line 12 "scripts/genksyms/keywords.gperf"
       {"__asm", ASM_KEYW},
       {""},
-#line 11 "scripts/genksyms/keywords.gperf"
+#line 13 "scripts/genksyms/keywords.gperf"
       {"__asm__", ASM_KEYW},
       {""}, {""},
-#line 54 "scripts/genksyms/keywords.gperf"
+#line 56 "scripts/genksyms/keywords.gperf"
       {"__typeof__", TYPEOF_KEYW},
       {""},
-#line 14 "scripts/genksyms/keywords.gperf"
+#line 16 "scripts/genksyms/keywords.gperf"
       {"__const", CONST_KEYW},
-#line 13 "scripts/genksyms/keywords.gperf"
-      {"__attribute__", ATTRIBUTE_KEYW},
 #line 15 "scripts/genksyms/keywords.gperf"
+      {"__attribute__", ATTRIBUTE_KEYW},
+#line 17 "scripts/genksyms/keywords.gperf"
       {"__const__", CONST_KEYW},
-#line 20 "scripts/genksyms/keywords.gperf"
+#line 22 "scripts/genksyms/keywords.gperf"
       {"__signed__", SIGNED_KEYW},
-#line 46 "scripts/genksyms/keywords.gperf"
+#line 48 "scripts/genksyms/keywords.gperf"
       {"static", STATIC_KEYW},
-#line 22 "scripts/genksyms/keywords.gperf"
-      {"__volatile__", VOLATILE_KEYW},
-#line 41 "scripts/genksyms/keywords.gperf"
+      {""},
+#line 43 "scripts/genksyms/keywords.gperf"
       {"int", INT_KEYW},
-#line 34 "scripts/genksyms/keywords.gperf"
+#line 36 "scripts/genksyms/keywords.gperf"
       {"char", CHAR_KEYW},
-#line 35 "scripts/genksyms/keywords.gperf"
+#line 37 "scripts/genksyms/keywords.gperf"
       {"const", CONST_KEYW},
-#line 47 "scripts/genksyms/keywords.gperf"
+#line 49 "scripts/genksyms/keywords.gperf"
       {"struct", STRUCT_KEYW},
-#line 26 "scripts/genksyms/keywords.gperf"
+#line 28 "scripts/genksyms/keywords.gperf"
       {"__restrict__", RESTRICT_KEYW},
-#line 27 "scripts/genksyms/keywords.gperf"
+#line 29 "scripts/genksyms/keywords.gperf"
       {"restrict", RESTRICT_KEYW},
-#line 25 "scripts/genksyms/keywords.gperf"
-      {"_restrict", RESTRICT_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
+#line 9 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
+#line 20 "scripts/genksyms/keywords.gperf"
       {"__inline__", INLINE_KEYW},
-#line 12 "scripts/genksyms/keywords.gperf"
-      {"__attribute", ATTRIBUTE_KEYW},
       {""},
-#line 16 "scripts/genksyms/keywords.gperf"
+#line 24 "scripts/genksyms/keywords.gperf"
+      {"__volatile__", VOLATILE_KEYW},
+#line 7 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 27 "scripts/genksyms/keywords.gperf"
+      {"_restrict", RESTRICT_KEYW},
+      {""},
+#line 14 "scripts/genksyms/keywords.gperf"
+      {"__attribute", ATTRIBUTE_KEYW},
+#line 8 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 18 "scripts/genksyms/keywords.gperf"
       {"__extension__", EXTENSION_KEYW},
-#line 37 "scripts/genksyms/keywords.gperf"
+#line 39 "scripts/genksyms/keywords.gperf"
       {"enum", ENUM_KEYW},
-#line 21 "scripts/genksyms/keywords.gperf"
-      {"__volatile", VOLATILE_KEYW},
-#line 38 "scripts/genksyms/keywords.gperf"
+#line 10 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 40 "scripts/genksyms/keywords.gperf"
       {"extern", EXTERN_KEYW},
       {""},
-#line 19 "scripts/genksyms/keywords.gperf"
+#line 21 "scripts/genksyms/keywords.gperf"
       {"__signed", SIGNED_KEYW},
-#line 9 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
-      {""},
-#line 53 "scripts/genksyms/keywords.gperf"
+#line 11 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 51 "scripts/genksyms/keywords.gperf"
+      {"union", UNION_KEYW},
+#line 55 "scripts/genksyms/keywords.gperf"
       {"typeof", TYPEOF_KEYW},
-#line 48 "scripts/genksyms/keywords.gperf"
+#line 50 "scripts/genksyms/keywords.gperf"
       {"typedef", TYPEDEF_KEYW},
-#line 17 "scripts/genksyms/keywords.gperf"
+#line 19 "scripts/genksyms/keywords.gperf"
       {"__inline", INLINE_KEYW},
-#line 33 "scripts/genksyms/keywords.gperf"
+#line 35 "scripts/genksyms/keywords.gperf"
       {"auto", AUTO_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
-      {"union", UNION_KEYW},
-      {""}, {""},
-#line 50 "scripts/genksyms/keywords.gperf"
-      {"unsigned", UNSIGNED_KEYW},
-#line 51 "scripts/genksyms/keywords.gperf"
-      {"void", VOID_KEYW},
-#line 44 "scripts/genksyms/keywords.gperf"
-      {"short", SHORT_KEYW},
+#line 23 "scripts/genksyms/keywords.gperf"
+      {"__volatile", VOLATILE_KEYW},
       {""}, {""},
 #line 52 "scripts/genksyms/keywords.gperf"
-      {"volatile", VOLATILE_KEYW},
-      {""},
-#line 39 "scripts/genksyms/keywords.gperf"
-      {"float", FLOAT_KEYW},
-#line 36 "scripts/genksyms/keywords.gperf"
-      {"double", DOUBLE_KEYW},
+      {"unsigned", UNSIGNED_KEYW},
       {""},
-#line 7 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
-      {""}, {""},
-#line 40 "scripts/genksyms/keywords.gperf"
+#line 46 "scripts/genksyms/keywords.gperf"
+      {"short", SHORT_KEYW},
+#line 42 "scripts/genksyms/keywords.gperf"
       {"inline", INLINE_KEYW},
-#line 8 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
-#line 43 "scripts/genksyms/keywords.gperf"
-      {"register", REGISTER_KEYW},
       {""},
-#line 24 "scripts/genksyms/keywords.gperf"
+#line 54 "scripts/genksyms/keywords.gperf"
+      {"volatile", VOLATILE_KEYW},
+#line 44 "scripts/genksyms/keywords.gperf"
+      {"long", LONG_KEYW},
+#line 26 "scripts/genksyms/keywords.gperf"
       {"_Bool", BOOL_KEYW},
-#line 45 "scripts/genksyms/keywords.gperf"
-      {"signed", SIGNED_KEYW},
       {""}, {""},
-#line 42 "scripts/genksyms/keywords.gperf"
-      {"long", LONG_KEYW}
+#line 45 "scripts/genksyms/keywords.gperf"
+      {"register", REGISTER_KEYW},
+#line 53 "scripts/genksyms/keywords.gperf"
+      {"void", VOID_KEYW},
+#line 41 "scripts/genksyms/keywords.gperf"
+      {"float", FLOAT_KEYW},
+#line 38 "scripts/genksyms/keywords.gperf"
+      {"double", DOUBLE_KEYW},
+      {""}, {""}, {""}, {""},
+#line 47 "scripts/genksyms/keywords.gperf"
+      {"signed", SIGNED_KEYW}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
index 8fe977a..e6349ac 100644 (file)
@@ -7,6 +7,8 @@ struct resword { const char *name; int token; }
 EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 __asm, ASM_KEYW
 __asm__, ASM_KEYW
 __attribute, ATTRIBUTE_KEYW
index 0308ecc..1ddcdd3 100755 (executable)
@@ -8,8 +8,6 @@ do_command()
 {
        if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then
                make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
-       elif [ -f ${srctree}/include/asm-$2/Kbuild ]; then
-               make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
        else
                printf "Ignoring arch: %s\n" ${arch}
        fi
index 80599e3..999e8a7 100644 (file)
@@ -27,6 +27,7 @@ oldconfig: $(obj)/conf
        $< -o $(Kconfig)
 
 silentoldconfig: $(obj)/conf
+       $(Q)mkdir -p include/generated
        $< -s $(Kconfig)
 
 localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
index b55e72f..c4dec80 100644 (file)
@@ -677,7 +677,7 @@ int conf_write_autoconf(void)
        struct symbol *sym;
        const char *str;
        const char *name;
-       FILE *out, *out_h;
+       FILE *out, *tristate, *out_h;
        time_t now;
        int i, l;
 
@@ -692,9 +692,16 @@ int conf_write_autoconf(void)
        if (!out)
                return 1;
 
+       tristate = fopen(".tmpconfig_tristate", "w");
+       if (!tristate) {
+               fclose(out);
+               return 1;
+       }
+
        out_h = fopen(".tmpconfig.h", "w");
        if (!out_h) {
                fclose(out);
+               fclose(tristate);
                return 1;
        }
 
@@ -707,6 +714,9 @@ int conf_write_autoconf(void)
                     "# %s"
                     "#\n",
                     sym_get_string_value(sym), ctime(&now));
+       fprintf(tristate, "#\n"
+                         "# Automatically generated - do not edit\n"
+                         "\n");
        fprintf(out_h, "/*\n"
                       " * Automatically generated C config: don't edit\n"
                       " * Linux kernel version: %s\n"
@@ -727,10 +737,14 @@ int conf_write_autoconf(void)
                                break;
                        case mod:
                                fprintf(out, "CONFIG_%s=m\n", sym->name);
+                               fprintf(tristate, "CONFIG_%s=M\n", sym->name);
                                fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
                                break;
                        case yes:
                                fprintf(out, "CONFIG_%s=y\n", sym->name);
+                               if (sym->type == S_TRISTATE)
+                                       fprintf(tristate, "CONFIG_%s=Y\n",
+                                                       sym->name);
                                fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
                                break;
                        }
@@ -772,13 +786,19 @@ int conf_write_autoconf(void)
                }
        }
        fclose(out);
+       fclose(tristate);
        fclose(out_h);
 
        name = getenv("KCONFIG_AUTOHEADER");
        if (!name)
-               name = "include/linux/autoconf.h";
+               name = "include/generated/autoconf.h";
        if (rename(".tmpconfig.h", name))
                return 1;
+       name = getenv("KCONFIG_TRISTATE");
+       if (!name)
+               name = "include/config/tristate.conf";
+       if (rename(".tmpconfig_tristate", name))
+               return 1;
        name = conf_get_autoconfig_name();
        /*
         * This must be the last step, kbuild has a dependency on auto.conf
index bce3d0f..23dbad8 100755 (executable)
@@ -14,7 +14,7 @@ vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
 # So "sudo make install" won't change the "compiled by <user>"
 # do "compiled by root"
 
-if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then
+if [ -r $TARGET -a ! -O include/generated/autoconf.h ]; then
   vecho "  SKIPPED $TARGET"
   exit 0
 fi
index 6c4ffc7..2092361 100644 (file)
@@ -15,7 +15,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include "modpost.h"
-#include "../../include/linux/autoconf.h"
+#include "../../include/generated/autoconf.h"
 #include "../../include/linux/license.h"
 
 /* Some toolchains use a `_' prefix for all user symbols. */
index f67cc88..62fcc3a 100644 (file)
@@ -77,9 +77,27 @@ clean-files += $(objtree)/binkernel.spec
 
 # Deb target
 # ---------------------------------------------------------------------------
+quiet_cmd_builddeb = BUILDDEB
+      cmd_builddeb = set -e; \
+       test `id -u` = 0 || \
+       test -n "$(KBUILD_PKG_ROOTCMD)" || { \
+               which fakeroot >/dev/null 2>&1 && \
+               KBUILD_PKG_ROOTCMD="fakeroot -u"; \
+       } || { \
+               echo; \
+               echo "builddeb must be run as root (or using fakeroot)."; \
+               echo "KBUILD_PKG_ROOTCMD is unset and fakeroot not found."; \
+               echo "Try setting KBUILD_PKG_ROOTCMD to a command to acquire"; \
+               echo "root privileges (e.g., 'fakeroot -u' or 'sudo')."; \
+               false; \
+       } && \
+       \
+       $$KBUILD_PKG_ROOTCMD $(CONFIG_SHELL) \
+               $(srctree)/scripts/package/builddeb
+
 deb-pkg: FORCE
        $(MAKE) KBUILD_SRC=
-       $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
+       $(call cmd,builddeb)
 
 clean-dirs += $(objtree)/debian/
 
index b1fd48d..51b2aa0 100644 (file)
@@ -101,7 +101,11 @@ esac
 #
 (
        cd "${tmpdir}"
-       tar cf - . | ${compress} > "${tarball}${file_ext}"
+       opts=
+       if tar --owner=root --group=root --help >/dev/null 2>&1; then
+               opts="--owner=root --group=root"
+       fi
+       tar cf - . $opts | ${compress} > "${tarball}${file_ext}"
 )
 
 echo "Tarball successfully created in ${tarball}${file_ext}"
index 9cf0a6f..92f09fe 100755 (executable)
@@ -113,13 +113,13 @@ $P =~ s@.*/@@g;
 
 my $V = '0.1';
 
-if ($#ARGV != 10) {
-       print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
+if ($#ARGV != 11) {
+       print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
        print "version: $V\n";
        exit(1);
 }
 
-my ($arch, $bits, $objdump, $objcopy, $cc,
+my ($arch, $endian, $bits, $objdump, $objcopy, $cc,
     $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
 
 # This file refers to mcount and shouldn't be ftraced, so lets' ignore it
@@ -295,6 +295,58 @@ if ($arch eq "x86_64") {
     $ld .= " -m elf64_sparc";
     $cc .= " -m64";
     $objcopy .= " -O elf64-sparc";
+} elsif ($arch eq "mips") {
+    # To enable module support, we need to enable the -mlong-calls option
+    # of gcc for module, after using this option, we can not get the real
+    # offset of the calling to _mcount, but the offset of the lui
+    # instruction or the addiu one. herein, we record the address of the
+    # first one, and then we can replace this instruction by a branch
+    # instruction to jump over the profiling function to filter the
+    # indicated functions, or swith back to the lui instruction to trace
+    # them, which means dynamic tracing.
+    #
+    #       c: 3c030000        lui     v1,0x0
+    #                  c: R_MIPS_HI16  _mcount
+    #                  c: R_MIPS_NONE  *ABS*
+    #                  c: R_MIPS_NONE  *ABS*
+    #      10: 64630000        daddiu  v1,v1,0
+    #                  10: R_MIPS_LO16 _mcount
+    #                  10: R_MIPS_NONE *ABS*
+    #                  10: R_MIPS_NONE *ABS*
+    #      14: 03e0082d        move    at,ra
+    #      18: 0060f809        jalr    v1
+    #
+    # for the kernel:
+    #
+    #     10:   03e0082d        move    at,ra
+    #    14:   0c000000        jal     0 <loongson_halt>
+    #                    14: R_MIPS_26   _mcount
+    #                    14: R_MIPS_NONE *ABS*
+    #                    14: R_MIPS_NONE *ABS*
+    #   18:   00020021        nop
+    if ($is_module eq "0") {
+           $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+    } else {
+           $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
+    }
+    $objdump .= " -Melf-trad".$endian."mips ";
+
+    if ($endian eq "big") {
+           $endian = " -EB ";
+           $ld .= " -melf".$bits."btsmip";
+    } else {
+           $endian = " -EL ";
+           $ld .= " -melf".$bits."ltsmip";
+    }
+
+    $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian;
+    $ld .= $endian;
+
+    if ($bits == 64) {
+           $function_regex =
+               "^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:";
+           $type = ".dword";
+    }
 } elsif ($arch eq "microblaze") {
     # Microblaze calls '_mcount' instead of plain 'mcount'.
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
index d52f7a0..1a0c44d 100755 (executable)
@@ -89,7 +89,13 @@ all_defconfigs()
 
 docscope()
 {
-       (echo \-k; echo \-q; all_sources) > cscope.files
+       # always use absolute paths for cscope, as recommended by cscope
+       # upstream
+       case "$tree" in
+               /*) ;;
+               *) tree=$PWD/$tree ;;
+       esac
+       (cd /; echo \-k; echo \-q; all_sources) > cscope.files
        cscope -b -f cscope.out
 }
 
index 30d459f..44d3978 100644 (file)
@@ -1,13 +1,5 @@
 /*
- * Copyright (c) 2002 - 2005 Tony Finch <dot@dotat.at>.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by Dave Yost.
- * It was rewritten to support ANSI C by Tony Finch. The original version of
- * unifdef carried the following copyright notice. None of its code remains
- * in this version (though some of the names remain).
- *
- * Copyright (c) 1985, 1993
- *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/*
+ * This code was derived from software contributed to Berkeley by Dave Yost.
+ * It was rewritten to support ANSI C by Tony Finch. The original version
+ * of unifdef carried the 4-clause BSD copyright licence. None of its code
+ * remains in this version (though some of the names remain) so it now
+ * carries a more liberal licence.
+ *
+ * The latest version is available from http://dotat.at/prog/unifdef
+ */
 
-#ifndef lint
-#if 0
-static const char copyright[] =
-"@(#) Copyright (c) 1985, 1993\n\
-       The Regents of the University of California.  All rights reserved.\n";
-#endif
-#ifdef __IDSTRING
-__IDSTRING(Berkeley, "@(#)unifdef.c    8.1 (Berkeley) 6/6/93");
-__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $");
-__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $");
-#endif
-#endif /* not lint */
-#ifdef __FBSDID
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $");
-#endif
+static const char * const copyright[] = {
+    "@(#) Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>\n",
+    "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $",
+};
 
 /*
  * unifdef - remove ifdef'ed lines
@@ -72,8 +61,6 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05
 #include <string.h>
 #include <unistd.h>
 
-size_t strlcpy(char *dst, const char *src, size_t siz);
-
 /* types of input lines: */
 typedef enum {
        LT_TRUEI,               /* a true #if with ignore flag */
@@ -90,6 +77,7 @@ typedef enum {
        LT_DODGY_LAST = LT_DODGY + LT_ENDIF,
        LT_PLAIN,               /* ordinary line */
        LT_EOF,                 /* end of file */
+       LT_ERROR,               /* unevaluable #if */
        LT_COUNT
 } Linetype;
 
@@ -100,7 +88,7 @@ static char const * const linetype_name[] = {
        "DODGY IF", "DODGY TRUE", "DODGY FALSE",
        "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE",
        "DODGY ELSE", "DODGY ENDIF",
-       "PLAIN", "EOF"
+       "PLAIN", "EOF", "ERROR"
 };
 
 /* state of #if processing */
@@ -168,11 +156,13 @@ static char const * const linestate_name[] = {
  * Globals.
  */
 
+static bool             compblank;             /* -B: compress blank lines */
+static bool             lnblank;               /* -b: blank deleted lines */
 static bool             complement;            /* -c: do the complement */
 static bool             debugging;             /* -d: debugging reports */
 static bool             iocccok;               /* -e: fewer IOCCC errors */
+static bool             strictlogic;           /* -K: keep ambiguous #ifs */
 static bool             killconsts;            /* -k: eval constant #ifs */
-static bool             lnblank;               /* -l: blank deleted lines */
 static bool             lnnum;                 /* -n: add #line directives */
 static bool             symlist;               /* -s: output symbol list */
 static bool             text;                  /* -t: this is a text file */
@@ -196,7 +186,9 @@ static bool             ignoring[MAXDEPTH]; /* ignore comments state */
 static int              stifline[MAXDEPTH];    /* start of current #if */
 static int              depth;                 /* current #if nesting */
 static int              delcount;              /* count of deleted lines */
-static bool             keepthis;              /* don't delete constant #if */
+static unsigned         blankcount;            /* count of blank lines */
+static unsigned         blankmax;              /* maximum recent blankcount */
+static bool             constexpr;             /* constant #if expression */
 
 static int              exitstat;              /* program exit status */
 
@@ -206,13 +198,14 @@ static void             done(void);
 static void             error(const char *);
 static int              findsym(const char *);
 static void             flushline(bool);
-static Linetype         get_line(void);
+static Linetype         parseline(void);
 static Linetype         ifeval(const char **);
 static void             ignoreoff(void);
 static void             ignoreon(void);
 static void             keywordedit(const char *);
 static void             nest(void);
 static void             process(void);
+static const char      *skipargs(const char *);
 static const char      *skipcomment(const char *);
 static const char      *skipsym(const char *);
 static void             state(Ifstate);
@@ -220,7 +213,7 @@ static int              strlcmp(const char *, const char *, size_t);
 static void             unnest(void);
 static void             usage(void);
 
-#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_')
+#define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
 /*
  * The main program.
@@ -230,7 +223,7 @@ main(int argc, char *argv[])
 {
        int opt;
 
-       while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1)
+       while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
                switch (opt) {
                case 'i': /* treat stuff controlled by these symbols as text */
                        /*
@@ -255,6 +248,13 @@ main(int argc, char *argv[])
                case 'I':
                        /* no-op for compatibility with cpp */
                        break;
+               case 'B': /* compress blank lines around removed section */
+                       compblank = true;
+                       break;
+               case 'b': /* blank deleted lines instead of omitting them */
+               case 'l': /* backwards compatibility */
+                       lnblank = true;
+                       break;
                case 'c': /* treat -D as -U and vice versa */
                        complement = true;
                        break;
@@ -264,12 +264,12 @@ main(int argc, char *argv[])
                case 'e': /* fewer errors from dodgy lines */
                        iocccok = true;
                        break;
+               case 'K': /* keep ambiguous #ifs */
+                       strictlogic = true;
+                       break;
                case 'k': /* process constant #ifs */
                        killconsts = true;
                        break;
-               case 'l': /* blank deleted lines instead of omitting them */
-                       lnblank = true;
-                       break;
                case 'n': /* add #line directive after deleted lines */
                        lnnum = true;
                        break;
@@ -284,6 +284,8 @@ main(int argc, char *argv[])
                }
        argc -= optind;
        argv += optind;
+       if (compblank && lnblank)
+               errx(2, "-B and -b are mutually exclusive");
        if (argc > 1) {
                errx(2, "can only do one file");
        } else if (argc == 1 && strcmp(*argv, "-") != 0) {
@@ -302,7 +304,7 @@ main(int argc, char *argv[])
 static void
 usage(void)
 {
-       fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]"
+       fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]"
            " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
        exit(2);
 }
@@ -383,46 +385,46 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
 /* IS_OUTSIDE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Eendif,
-  print, done },
+  print, done,  abort },
 /* IS_FALSE_PREFIX */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_PREFIX */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_PASS_MIDDLE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Pelif, Oelif, Oelif, Pelse, Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_MIDDLE */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_MIDDLE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eioccc,Eioccc,Eioccc,Eioccc,Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_PASS_ELSE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_ELSE */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_ELSE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Eioccc,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_TRAILER */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc,
-  drop,  Eeof }
+  drop,  Eeof,  abort }
 /*TRUEI  FALSEI IF     TRUE   FALSE  ELIF   ELTRUE ELFALSE ELSE  ENDIF
   TRUEI  FALSEI IF     TRUE   FALSE  ELIF   ELTRUE ELFALSE ELSE  ENDIF (DODGY)
-  PLAIN  EOF */
+  PLAIN  EOF    ERROR */
 };
 
 /*
@@ -463,9 +465,11 @@ keywordedit(const char *replacement)
 static void
 nest(void)
 {
-       depth += 1;
-       if (depth >= MAXDEPTH)
+       if (depth > MAXDEPTH-1)
+               abort(); /* bug */
+       if (depth == MAXDEPTH-1)
                error("Too many levels of nesting");
+       depth += 1;
        stifline[depth] = linenum;
 }
 static void
@@ -490,15 +494,23 @@ flushline(bool keep)
        if (symlist)
                return;
        if (keep ^ complement) {
-               if (lnnum && delcount > 0)
-                       printf("#line %d\n", linenum);
-               fputs(tline, stdout);
-               delcount = 0;
+               bool blankline = tline[strspn(tline, " \t\n")] == '\0';
+               if (blankline && compblank && blankcount != blankmax) {
+                       delcount += 1;
+                       blankcount += 1;
+               } else {
+                       if (lnnum && delcount > 0)
+                               printf("#line %d\n", linenum);
+                       fputs(tline, stdout);
+                       delcount = 0;
+                       blankmax = blankcount = blankline ? blankcount + 1 : 0;
+               }
        } else {
                if (lnblank)
                        putc('\n', stdout);
                exitstat = 1;
                delcount += 1;
+               blankcount = 0;
        }
 }
 
@@ -510,9 +522,12 @@ process(void)
 {
        Linetype lineval;
 
+       /* When compressing blank lines, act as if the file
+          is preceded by a large number of blank lines. */
+       blankmax = blankcount = 1000;
        for (;;) {
                linenum++;
-               lineval = get_line();
+               lineval = parseline();
                trans_table[ifstate[depth]][lineval]();
                debug("process %s -> %s depth %d",
                    linetype_name[lineval],
@@ -526,7 +541,7 @@ process(void)
  * help from skipcomment().
  */
 static Linetype
-get_line(void)
+parseline(void)
 {
        const char *cp;
        int cursym;
@@ -595,9 +610,21 @@ get_line(void)
                        if (incomment)
                                linestate = LS_DIRTY;
                }
-               /* skipcomment should have changed the state */
-               if (linestate == LS_HASH)
-                       abort(); /* bug */
+               /* skipcomment normally changes the state, except
+                  if the last line of the file lacks a newline, or
+                  if there is too much whitespace in a directive */
+               if (linestate == LS_HASH) {
+                       size_t len = cp - tline;
+                       if (fgets(tline + len, MAXLINE - len, input) == NULL) {
+                               /* append the missing newline */
+                               tline[len+0] = '\n';
+                               tline[len+1] = '\0';
+                               cp++;
+                               linestate = LS_START;
+                       } else {
+                               linestate = LS_DIRTY;
+                       }
+               }
        }
        if (linestate == LS_DIRTY) {
                while (*cp != '\0')
@@ -610,17 +637,40 @@ get_line(void)
 
 /*
  * These are the binary operators that are supported by the expression
- * evaluator. Note that if support for division is added then we also
- * need short-circuiting booleans because of divide-by-zero.
+ * evaluator.
  */
-static int op_lt(int a, int b) { return (a < b); }
-static int op_gt(int a, int b) { return (a > b); }
-static int op_le(int a, int b) { return (a <= b); }
-static int op_ge(int a, int b) { return (a >= b); }
-static int op_eq(int a, int b) { return (a == b); }
-static int op_ne(int a, int b) { return (a != b); }
-static int op_or(int a, int b) { return (a || b); }
-static int op_and(int a, int b) { return (a && b); }
+static Linetype op_strict(int *p, int v, Linetype at, Linetype bt) {
+       if(at == LT_IF || bt == LT_IF) return (LT_IF);
+       return (*p = v, v ? LT_TRUE : LT_FALSE);
+}
+static Linetype op_lt(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a < b, at, bt);
+}
+static Linetype op_gt(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a > b, at, bt);
+}
+static Linetype op_le(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a <= b, at, bt);
+}
+static Linetype op_ge(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a >= b, at, bt);
+}
+static Linetype op_eq(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a == b, at, bt);
+}
+static Linetype op_ne(int *p, Linetype at, int a, Linetype bt, int b) {
+       return op_strict(p, a != b, at, bt);
+}
+static Linetype op_or(int *p, Linetype at, int a, Linetype bt, int b) {
+       if (!strictlogic && (at == LT_TRUE || bt == LT_TRUE))
+               return (*p = 1, LT_TRUE);
+       return op_strict(p, a || b, at, bt);
+}
+static Linetype op_and(int *p, Linetype at, int a, Linetype bt, int b) {
+       if (!strictlogic && (at == LT_FALSE || bt == LT_FALSE))
+               return (*p = 0, LT_FALSE);
+       return op_strict(p, a && b, at, bt);
+}
 
 /*
  * An evaluation function takes three arguments, as follows: (1) a pointer to
@@ -629,8 +679,8 @@ static int op_and(int a, int b) { return (a && b); }
  * value of the expression; and (3) a pointer to a char* that points to the
  * expression to be evaluated and that is updated to the end of the expression
  * when evaluation is complete. The function returns LT_FALSE if the value of
- * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the
- * expression could not be evaluated.
+ * the expression is zero, LT_TRUE if it is non-zero, LT_IF if the expression
+ * depends on an unknown symbol, or LT_ERROR if there is a parse failure.
  */
 struct ops;
 
@@ -649,7 +699,7 @@ static const struct ops {
        eval_fn *inner;
        struct op {
                const char *str;
-               int (*fn)(int, int);
+               Linetype (*fn)(int *, Linetype, int, Linetype, int);
        } op[5];
 } eval_ops[] = {
        { eval_table, { { "||", op_or } } },
@@ -664,8 +714,8 @@ static const struct ops {
 
 /*
  * Function for evaluating the innermost parts of expressions,
- * viz. !expr (expr) defined(symbol) symbol number
- * We reset the keepthis flag when we find a non-constant subexpression.
+ * viz. !expr (expr) number defined(symbol) symbol
+ * We reset the constexpr flag in the last two cases.
  */
 static Linetype
 eval_unary(const struct ops *ops, int *valp, const char **cpp)
@@ -673,68 +723,83 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp)
        const char *cp;
        char *ep;
        int sym;
+       bool defparen;
+       Linetype lt;
 
        cp = skipcomment(*cpp);
        if (*cp == '!') {
                debug("eval%d !", ops - eval_ops);
                cp++;
-               if (eval_unary(ops, valp, &cp) == LT_IF) {
-                       *cpp = cp;
-                       return (LT_IF);
+               lt = eval_unary(ops, valp, &cp);
+               if (lt == LT_ERROR)
+                       return (LT_ERROR);
+               if (lt != LT_IF) {
+                       *valp = !*valp;
+                       lt = *valp ? LT_TRUE : LT_FALSE;
                }
-               *valp = !*valp;
        } else if (*cp == '(') {
                cp++;
                debug("eval%d (", ops - eval_ops);
-               if (eval_table(eval_ops, valp, &cp) == LT_IF)
-                       return (LT_IF);
+               lt = eval_table(eval_ops, valp, &cp);
+               if (lt == LT_ERROR)
+                       return (LT_ERROR);
                cp = skipcomment(cp);
                if (*cp++ != ')')
-                       return (LT_IF);
+                       return (LT_ERROR);
        } else if (isdigit((unsigned char)*cp)) {
                debug("eval%d number", ops - eval_ops);
                *valp = strtol(cp, &ep, 0);
+               if (ep == cp)
+                       return (LT_ERROR);
+               lt = *valp ? LT_TRUE : LT_FALSE;
                cp = skipsym(cp);
        } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) {
                cp = skipcomment(cp+7);
                debug("eval%d defined", ops - eval_ops);
-               if (*cp++ != '(')
-                       return (LT_IF);
-               cp = skipcomment(cp);
+               if (*cp == '(') {
+                       cp = skipcomment(cp+1);
+                       defparen = true;
+               } else {
+                       defparen = false;
+               }
                sym = findsym(cp);
-               cp = skipsym(cp);
-               cp = skipcomment(cp);
-               if (*cp++ != ')')
-                       return (LT_IF);
-               if (sym >= 0)
+               if (sym < 0) {
+                       lt = LT_IF;
+               } else {
                        *valp = (value[sym] != NULL);
-               else {
-                       *cpp = cp;
-                       return (LT_IF);
+                       lt = *valp ? LT_TRUE : LT_FALSE;
                }
-               keepthis = false;
+               cp = skipsym(cp);
+               cp = skipcomment(cp);
+               if (defparen && *cp++ != ')')
+                       return (LT_ERROR);
+               constexpr = false;
        } else if (!endsym(*cp)) {
                debug("eval%d symbol", ops - eval_ops);
                sym = findsym(cp);
-               if (sym < 0)
-                       return (LT_IF);
-               if (value[sym] == NULL)
+               cp = skipsym(cp);
+               if (sym < 0) {
+                       lt = LT_IF;
+                       cp = skipargs(cp);
+               } else if (value[sym] == NULL) {
                        *valp = 0;
-               else {
+                       lt = LT_FALSE;
+               } else {
                        *valp = strtol(value[sym], &ep, 0);
                        if (*ep != '\0' || ep == value[sym])
-                               return (LT_IF);
+                               return (LT_ERROR);
+                       lt = *valp ? LT_TRUE : LT_FALSE;
+                       cp = skipargs(cp);
                }
-               cp = skipsym(cp);
-               keepthis = false;
+               constexpr = false;
        } else {
                debug("eval%d bad expr", ops - eval_ops);
-               return (LT_IF);
+               return (LT_ERROR);
        }
 
        *cpp = cp;
        debug("eval%d = %d", ops - eval_ops, *valp);
-       return (*valp ? LT_TRUE : LT_FALSE);
+       return (lt);
 }
 
 /*
@@ -746,11 +811,13 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
        const struct op *op;
        const char *cp;
        int val;
-       Linetype lhs, rhs;
+       Linetype lt, rt;
 
        debug("eval%d", ops - eval_ops);
        cp = *cpp;
-       lhs = ops->inner(ops+1, valp, &cp);
+       lt = ops->inner(ops+1, valp, &cp);
+       if (lt == LT_ERROR)
+               return (LT_ERROR);
        for (;;) {
                cp = skipcomment(cp);
                for (op = ops->op; op->str != NULL; op++)
@@ -760,32 +827,16 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
                        break;
                cp += strlen(op->str);
                debug("eval%d %s", ops - eval_ops, op->str);
-               rhs = ops->inner(ops+1, &val, &cp);
-               if (op->fn == op_and && (lhs == LT_FALSE || rhs == LT_FALSE)) {
-                       debug("eval%d: and always false", ops - eval_ops);
-                       if (lhs == LT_IF)
-                               *valp = val;
-                       lhs = LT_FALSE;
-                       continue;
-               }
-               if (op->fn == op_or && (lhs == LT_TRUE || rhs == LT_TRUE)) {
-                       debug("eval%d: or always true", ops - eval_ops);
-                       if (lhs == LT_IF)
-                               *valp = val;
-                       lhs = LT_TRUE;
-                       continue;
-               }
-               if (rhs == LT_IF)
-                       lhs = LT_IF;
-               if (lhs != LT_IF)
-                       *valp = op->fn(*valp, val);
+               rt = ops->inner(ops+1, &val, &cp);
+               if (rt == LT_ERROR)
+                       return (LT_ERROR);
+               lt = op->fn(valp, lt, *valp, rt, val);
        }
 
        *cpp = cp;
        debug("eval%d = %d", ops - eval_ops, *valp);
-       if (lhs != LT_IF)
-               lhs = (*valp ? LT_TRUE : LT_FALSE);
-       return lhs;
+       debug("eval%d lt = %s", ops - eval_ops, linetype_name[lt]);
+       return (lt);
 }
 
 /*
@@ -796,17 +847,14 @@ eval_table(const struct ops *ops, int *valp, const char **cpp)
 static Linetype
 ifeval(const char **cpp)
 {
-       const char *cp = *cpp;
        int ret;
-       int val;
+       int val = 0;
 
        debug("eval %s", *cpp);
-       keepthis = killconsts ? false : true;
-       ret = eval_table(eval_ops, &val, &cp);
-       if (ret != LT_IF)
-               *cpp = cp;
+       constexpr = killconsts ? false : true;
+       ret = eval_table(eval_ops, &val, cpp);
        debug("eval = %d", val);
-       return (keepthis ? LT_IF : ret);
+       return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret);
 }
 
 /*
@@ -918,6 +966,31 @@ skipcomment(const char *cp)
 }
 
 /*
+ * Skip macro arguments.
+ */
+static const char *
+skipargs(const char *cp)
+{
+       const char *ocp = cp;
+       int level = 0;
+       cp = skipcomment(cp);
+       if (*cp != '(')
+               return (cp);
+       do {
+               if (*cp == '(')
+                       level++;
+               if (*cp == ')')
+                       level--;
+               cp = skipcomment(cp+1);
+       } while (level != 0 && *cp != '\0');
+       if (level == 0)
+               return (cp);
+       else
+       /* Rewind and re-detect the syntax error later. */
+               return (ocp);
+}
+
+/*
  * Skip over an identifier.
  */
 static const char *
@@ -929,7 +1002,7 @@ skipsym(const char *cp)
 }
 
 /*
- * Look for the symbol in the symbol table. If is is found, we return
+ * Look for the symbol in the symbol table. If it is found, we return
  * the symbol table index, else we return -1.
  */
 static int
index bb44e35..da20a19 100644 (file)
@@ -8,7 +8,8 @@ subdir-$(CONFIG_SECURITY_SMACK)         += smack
 subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
 
 # always enable default capabilities
-obj-y          += commoncap.o min_addr.o
+obj-y                                  += commoncap.o
+obj-$(CONFIG_MMU)                      += min_addr.o
 
 # Object file lists
 obj-$(CONFIG_SECURITY)                 += security.o capability.o
index 06ec722..e9c2e7c 100644 (file)
@@ -1194,7 +1194,7 @@ long keyctl_get_security(key_serial_t keyid,
                 * have the authorisation token handy */
                instkey = key_get_instantiation_authkey(keyid);
                if (IS_ERR(instkey))
-                       return PTR_ERR(key_ref);
+                       return PTR_ERR(instkey);
                key_put(instkey);
 
                key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0);
@@ -1236,6 +1236,7 @@ long keyctl_get_security(key_serial_t keyid,
  */
 long keyctl_session_to_parent(void)
 {
+#ifdef TIF_NOTIFY_RESUME
        struct task_struct *me, *parent;
        const struct cred *mycred, *pcred;
        struct cred *cred, *oldcred;
@@ -1326,6 +1327,15 @@ not_permitted:
 error_keyring:
        key_ref_put(keyring_r);
        return ret;
+
+#else /* !TIF_NOTIFY_RESUME */
+       /*
+        * To be removed when TIF_NOTIFY_RESUME has been implemented on
+        * m68k/xtensa
+        */
+#warning TIF_NOTIFY_RESUME not implemented
+       return -EOPNOTSUPP;
+#endif /* !TIF_NOTIFY_RESUME */
 }
 
 /*****************************************************************************/
index fc43c9d..e86f297 100644 (file)
@@ -43,7 +43,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write,
        return ret;
 }
 
-int __init init_mmap_min_addr(void)
+static int __init init_mmap_min_addr(void)
 {
        update_mmap_min_addr();
 
index a09c03c..c578c28 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "hda_codec.h"
 #include "hda_local.h"
+#include "hda_beep.h"
 
 #define CXT_PIN_DIR_IN              0x00
 #define CXT_PIN_DIR_OUT             0x01
@@ -111,6 +112,7 @@ struct conexant_spec {
        unsigned int dell_automute;
        unsigned int port_d_mode;
        unsigned char ext_mic_bias;
+       unsigned int dell_vostro;
 };
 
 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -476,6 +478,7 @@ static void conexant_free(struct hda_codec *codec)
                snd_array_free(&spec->jacks);
        }
 #endif
+       snd_hda_detach_beep_device(codec);
        kfree(codec->spec);
 }
 
@@ -2109,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int val;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT;
 
-       val = snd_hda_codec_read(codec, 0x17, 0,
-               AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT);
+       val = snd_hda_codec_read(codec, nid, 0,
+               AC_VERB_GET_AMP_GAIN_MUTE, inout);
 
        ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
        return 0;
@@ -2123,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
        unsigned int idx;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT;
 
        if (!imux->num_items)
                return 0;
@@ -2130,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
 
-       snd_hda_codec_write_cache(codec, 0x17, 0,
+       snd_hda_codec_write_cache(codec, nid, 0,
                AC_VERB_SET_AMP_GAIN_MUTE,
-               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
+               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
                        imux->items[idx].index);
 
        return 1;
@@ -2201,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
 
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Analog Mic Boost Capture Enum",
+               .name = "Ext Mic Boost Capture Enum",
                .info = cxt5066_mic_boost_mux_enum_info,
                .get = cxt5066_mic_boost_mux_enum_get,
                .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x17,
        },
 
        HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
@@ -2212,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
        {}
 };
 
+static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Int Mic Boost Capture Enum",
+               .info = cxt5066_mic_boost_mux_enum_info,
+               .get = cxt5066_mic_boost_mux_enum_get,
+               .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x23 | 0x100,
+       },
+       HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
+       {}
+};
+
 static struct hda_verb cxt5066_init_verbs[] = {
        {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
@@ -2397,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
 /* initialize jack-sensing, too */
 static int cxt5066_init(struct hda_codec *codec)
 {
+       struct conexant_spec *spec = codec->spec;
+
        snd_printdd("CXT5066: init\n");
        conexant_init(codec);
        if (codec->patch_ops.unsol_event) {
                cxt5066_hp_automute(codec);
-               cxt5066_automic(codec);
+               if (spec->dell_vostro)
+                       cxt5066_vostro_automic(codec);
+               else
+                       cxt5066_automic(codec);
        }
        return 0;
 }
@@ -2500,7 +2528,10 @@ static int patch_cxt5066(struct hda_codec *codec)
                spec->init_verbs[0] = cxt5066_init_verbs_vostro;
                spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
                spec->mixers[spec->num_mixers++] = cxt5066_mixers;
+               spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
                spec->port_d_mode = 0;
+               spec->dell_vostro = 1;
+               snd_hda_attach_beep_device(codec, 0x13);
 
                /* no S/PDIF out */
                spec->multiout.dig_out_nid = 0;
index 20c1828..c746505 100644 (file)
@@ -131,8 +131,8 @@ enum {
 enum {
        ALC269_BASIC,
        ALC269_QUANTA_FL1,
-       ALC269_ASUS_EEEPC_P703,
-       ALC269_ASUS_EEEPC_P901,
+       ALC269_ASUS_AMIC,
+       ALC269_ASUS_DMIC,
        ALC269_FUJITSU,
        ALC269_LIFEBOOK,
        ALC269_AUTO,
@@ -188,6 +188,8 @@ enum {
        ALC663_ASUS_MODE4,
        ALC663_ASUS_MODE5,
        ALC663_ASUS_MODE6,
+       ALC663_ASUS_MODE7,
+       ALC663_ASUS_MODE8,
        ALC272_DELL,
        ALC272_DELL_ZM1,
        ALC272_SAMSUNG_NC10,
@@ -335,6 +337,9 @@ struct alc_spec {
        /* hooks */
        void (*init_hook)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       void (*power_hook)(struct hda_codec *codec, int power);
+#endif
 
        /* for pin sensing */
        unsigned int sense_updated: 1;
@@ -386,6 +391,7 @@ struct alc_config_preset {
        void (*init_hook)(struct hda_codec *);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_amp_list *loopbacks;
+       void (*power_hook)(struct hda_codec *codec, int power);
 #endif
 };
 
@@ -898,6 +904,7 @@ static void setup_preset(struct hda_codec *codec,
        spec->unsol_event = preset->unsol_event;
        spec->init_hook = preset->init_hook;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+       spec->power_hook = preset->power_hook;
        spec->loopback.amplist = preset->loopbacks;
 #endif
 
@@ -1663,9 +1670,6 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
 /*  some bit here disables the other DACs. Init=0x4900 */
        {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
        {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* Enable amplifiers */
-       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
 /* DMIC fix
  * This laptop has a stereo digital microphone. The mics are only 1cm apart
  * which makes the stereo useless. However, either the mic or the ALC889
@@ -1778,6 +1782,25 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+               HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
 static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -1808,6 +1831,16 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x1b;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void alc889_power_eapd(struct hda_codec *codec, int power)
+{
+       snd_hda_codec_write(codec, 0x14, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+       snd_hda_codec_write(codec, 0x15, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+}
+#endif
+
 /*
  * ALC880 3-stack model
  *
@@ -3601,12 +3634,29 @@ static void alc_free(struct hda_codec *codec)
        snd_hda_detach_beep_device(codec);
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_suspend(struct hda_codec *codec, pm_message_t state)
+{
+       struct alc_spec *spec = codec->spec;
+       if (spec && spec->power_hook)
+               spec->power_hook(codec, 0);
+       return 0;
+}
+#endif
+
 #ifdef SND_HDA_NEEDS_RESUME
 static int alc_resume(struct hda_codec *codec)
 {
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       struct alc_spec *spec = codec->spec;
+#endif
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       if (spec && spec->power_hook)
+               spec->power_hook(codec, 1);
+#endif
        return 0;
 }
 #endif
@@ -3623,6 +3673,7 @@ static struct hda_codec_ops alc_patch_ops = {
        .resume = alc_resume,
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+       .suspend = alc_suspend,
        .check_power_status = alc_check_power_status,
 #endif
 };
@@ -8919,7 +8970,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
-       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
        SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
@@ -9282,6 +9333,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
@@ -9378,10 +9430,11 @@ static struct alc_config_preset alc882_presets[] = {
                .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_8930G] = {
-               .mixers = { alc888_base_mixer,
+               .mixers = { alc889_acer_aspire_8930g_mixer,
                                alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-                               alc889_acer_aspire_8930g_verbs },
+                               alc889_acer_aspire_8930g_verbs,
+                               alc889_eapd_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
@@ -9398,6 +9451,9 @@ static struct alc_config_preset alc882_presets[] = {
                .unsol_event = alc_automute_amp_unsol_event,
                .setup = alc889_acer_aspire_8930g_setup,
                .init_hook = alc_automute_amp,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+               .power_hook = alc889_power_eapd,
+#endif
        },
        [ALC888_ACER_ASPIRE_7730G] = {
                .mixers = { alc883_3ST_6ch_mixer,
@@ -9428,6 +9484,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
@@ -9489,6 +9546,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_lenovo_101e_capture_source,
@@ -9668,6 +9726,7 @@ static struct alc_config_preset alc882_presets[] = {
                        alc880_gpio1_init_verbs },
                .adc_nids = alc883_adc_nids,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+               .capsrc_nids = alc883_capsrc_nids,
                .dac_nids = alc883_dac_nids,
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .channel_mode = alc889A_mb31_6ch_modes,
@@ -10678,6 +10737,13 @@ static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
        {}
 };
 
+static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+       /* Front Mic pin: input vref at 50% */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {}
+};
+
 static struct hda_input_mux alc262_fujitsu_capture_source = {
        .num_items = 3,
        .items = {
@@ -11720,7 +11786,8 @@ static struct alc_config_preset alc262_presets[] = {
        [ALC262_LENOVO_3000] = {
                .mixers = { alc262_lenovo_3000_mixer },
                .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-                               alc262_lenovo_3000_unsol_verbs },
+                               alc262_lenovo_3000_unsol_verbs,
+                               alc262_lenovo_3000_init_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@ -13232,10 +13299,12 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = {
 /* toggle speaker-output according to the hp-jack state */
 static void alc269_speaker_automute(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+       unsigned int nid = spec->autocfg.hp_pins[0];
        unsigned int present;
        unsigned char bits;
 
-       present = snd_hda_jack_detect(codec, 0x15);
+       present = snd_hda_jack_detect(codec, nid);
        bits = present ? AMP_IN_MUTE(0) : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
                                AMP_IN_MUTE(0), bits);
@@ -13460,8 +13529,8 @@ static void alc269_auto_init(struct hda_codec *codec)
 static const char *alc269_models[ALC269_MODEL_LAST] = {
        [ALC269_BASIC]                  = "basic",
        [ALC269_QUANTA_FL1]             = "quanta",
-       [ALC269_ASUS_EEEPC_P703]        = "eeepc-p703",
-       [ALC269_ASUS_EEEPC_P901]        = "eeepc-p901",
+       [ALC269_ASUS_AMIC]              = "asus-amic",
+       [ALC269_ASUS_DMIC]              = "asus-dmic",
        [ALC269_FUJITSU]                = "fujitsu",
        [ALC269_LIFEBOOK]               = "lifebook",
        [ALC269_AUTO]                   = "auto",
@@ -13470,18 +13539,41 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
 static struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
        SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
-                     ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703),
-        SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703),
+                     ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-                     ALC269_ASUS_EEEPC_P901),
+                     ALC269_ASUS_DMIC),
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-                     ALC269_ASUS_EEEPC_P901),
-        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901),
+                     ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC),
        SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
        {}
@@ -13511,7 +13603,7 @@ static struct alc_config_preset alc269_presets[] = {
                .setup = alc269_quanta_fl1_setup,
                .init_hook = alc269_quanta_fl1_init_hook,
        },
-       [ALC269_ASUS_EEEPC_P703] = {
+       [ALC269_ASUS_AMIC] = {
                .mixers = { alc269_eeepc_mixer },
                .cap_mixer = alc269_epc_capture_mixer,
                .init_verbs = { alc269_init_verbs,
@@ -13525,7 +13617,7 @@ static struct alc_config_preset alc269_presets[] = {
                .setup = alc269_eeepc_amic_setup,
                .init_hook = alc269_eeepc_inithook,
        },
-       [ALC269_ASUS_EEEPC_P901] = {
+       [ALC269_ASUS_DMIC] = {
                .mixers = { alc269_eeepc_mixer },
                .cap_mixer = alc269_epc_capture_mixer,
                .init_verbs = { alc269_init_verbs,
@@ -16160,6 +16252,52 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = {
        { } /* end */
 };
 
+static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
+
+static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
+
+static struct snd_kcontrol_new alc663_mode7_mixer[] = {
+       HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+       HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+       HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+       HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       { } /* end */
+};
+
+static struct snd_kcontrol_new alc663_mode8_mixer[] = {
+       HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+       HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+       HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+       HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
 static struct snd_kcontrol_new alc662_chmode_mixer[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -16447,6 +16585,45 @@ static struct hda_verb alc272_dell_init_verbs[] = {
        {}
 };
 
+static struct hda_verb alc663_mode7_init_verbs[] = {
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Headphone */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+       {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
+static struct hda_verb alc663_mode8_init_verbs[] = {
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},  /* Headphone */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
 static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
@@ -16626,6 +16803,54 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
        }
 }
 
+static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present1, present2;
+
+       present1 = snd_hda_codec_read(codec, 0x1b, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+       present2 = snd_hda_codec_read(codec, 0x21, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+
+       if (present1 || present2) {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       } else {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       }
+}
+
+static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present1, present2;
+
+       present1 = snd_hda_codec_read(codec, 0x21, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+       present2 = snd_hda_codec_read(codec, 0x15, 0,
+                       AC_VERB_GET_PIN_SENSE, 0)
+                       & AC_PINSENSE_PRESENCE;
+
+       if (present1 || present2) {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       } else {
+               snd_hda_codec_write_cache(codec, 0x14, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               snd_hda_codec_write_cache(codec, 0x17, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       }
+}
+
 static void alc663_m51va_unsol_event(struct hda_codec *codec,
                                           unsigned int res)
 {
@@ -16645,7 +16870,7 @@ static void alc663_m51va_setup(struct hda_codec *codec)
        spec->ext_mic.pin = 0x18;
        spec->ext_mic.mux_idx = 0;
        spec->int_mic.pin = 0x12;
-       spec->int_mic.mux_idx = 1;
+       spec->int_mic.mux_idx = 9;
        spec->auto_mic = 1;
 }
 
@@ -16657,7 +16882,17 @@ static void alc663_m51va_inithook(struct hda_codec *codec)
 
 /* ***************** Mode1 ******************************/
 #define alc663_mode1_unsol_event       alc663_m51va_unsol_event
-#define alc663_mode1_setup             alc663_m51va_setup
+
+static void alc663_mode1_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
+}
+
 #define alc663_mode1_inithook          alc663_m51va_inithook
 
 /* ***************** Mode2 ******************************/
@@ -16674,7 +16909,7 @@ static void alc662_mode2_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc662_mode2_setup     alc663_m51va_setup
+#define alc662_mode2_setup     alc663_mode1_setup
 
 static void alc662_mode2_inithook(struct hda_codec *codec)
 {
@@ -16695,7 +16930,7 @@ static void alc663_mode3_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode3_setup     alc663_m51va_setup
+#define alc663_mode3_setup     alc663_mode1_setup
 
 static void alc663_mode3_inithook(struct hda_codec *codec)
 {
@@ -16716,7 +16951,7 @@ static void alc663_mode4_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode4_setup     alc663_m51va_setup
+#define alc663_mode4_setup     alc663_mode1_setup
 
 static void alc663_mode4_inithook(struct hda_codec *codec)
 {
@@ -16737,7 +16972,7 @@ static void alc663_mode5_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode5_setup     alc663_m51va_setup
+#define alc663_mode5_setup     alc663_mode1_setup
 
 static void alc663_mode5_inithook(struct hda_codec *codec)
 {
@@ -16758,7 +16993,7 @@ static void alc663_mode6_unsol_event(struct hda_codec *codec,
        }
 }
 
-#define alc663_mode6_setup     alc663_m51va_setup
+#define alc663_mode6_setup     alc663_mode1_setup
 
 static void alc663_mode6_inithook(struct hda_codec *codec)
 {
@@ -16766,6 +17001,50 @@ static void alc663_mode6_inithook(struct hda_codec *codec)
        alc_mic_automute(codec);
 }
 
+/* ***************** Mode7 ******************************/
+static void alc663_mode7_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_two_hp_m7_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
+}
+
+#define alc663_mode7_setup     alc663_mode1_setup
+
+static void alc663_mode7_inithook(struct hda_codec *codec)
+{
+       alc663_two_hp_m7_speaker_automute(codec);
+       alc_mic_automute(codec);
+}
+
+/* ***************** Mode8 ******************************/
+static void alc663_mode8_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_two_hp_m8_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
+}
+
+#define alc663_mode8_setup     alc663_m51va_setup
+
+static void alc663_mode8_inithook(struct hda_codec *codec)
+{
+       alc663_two_hp_m8_speaker_automute(codec);
+       alc_mic_automute(codec);
+}
+
 static void alc663_g71v_hp_automute(struct hda_codec *codec)
 {
        unsigned int present;
@@ -16900,6 +17179,8 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
        [ALC663_ASUS_MODE4] = "asus-mode4",
        [ALC663_ASUS_MODE5] = "asus-mode5",
        [ALC663_ASUS_MODE6] = "asus-mode6",
+       [ALC663_ASUS_MODE7] = "asus-mode7",
+       [ALC663_ASUS_MODE8] = "asus-mode8",
        [ALC272_DELL]           = "dell",
        [ALC272_DELL_ZM1]       = "dell-zm1",
        [ALC272_SAMSUNG_NC10]   = "samsung-nc10",
@@ -16916,12 +17197,22 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
+       SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
+       SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
+       SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
+       SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
+       SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
+       SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
        SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
        SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
@@ -17205,6 +17496,36 @@ static struct alc_config_preset alc662_presets[] = {
                .setup = alc663_mode6_setup,
                .init_hook = alc663_mode6_inithook,
        },
+       [ALC663_ASUS_MODE7] = {
+               .mixers = { alc663_mode7_mixer },
+               .cap_mixer = alc662_auto_capture_mixer,
+               .init_verbs = { alc662_init_verbs,
+                               alc663_mode7_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .hp_nid = 0x03,
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .unsol_event = alc663_mode7_unsol_event,
+               .setup = alc663_mode7_setup,
+               .init_hook = alc663_mode7_inithook,
+       },
+       [ALC663_ASUS_MODE8] = {
+               .mixers = { alc663_mode8_mixer },
+               .cap_mixer = alc662_auto_capture_mixer,
+               .init_verbs = { alc662_init_verbs,
+                               alc663_mode8_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .hp_nid = 0x03,
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .unsol_event = alc663_mode8_unsol_event,
+               .setup = alc663_mode8_setup,
+               .init_hook = alc663_mode8_inithook,
+       },
        [ALC272_DELL] = {
                .mixers = { alc663_m51va_mixer },
                .cap_mixer = alc272_auto_capture_mixer,
@@ -17688,7 +18009,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
        { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
        { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
+       { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
        { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
+       { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
index b69861d..3ef16bb 100644 (file)
@@ -470,7 +470,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
 
 static int __init ak4642_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&ak4642_i2c_driver);
 #endif
index bbc72c2..81b8c9d 100644 (file)
@@ -191,6 +191,7 @@ static int ac97_analog_prepare(struct snd_pcm_substream *substream,
        vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
 
        vra |= 0x1; /* enable variable rate audio */
+       vra &= ~0x4; /* disable SPDIF output */
 
        stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
 
@@ -221,22 +222,6 @@ static int ac97_digital_prepare(struct snd_pcm_substream *substream,
        return stac9766_ac97_write(codec, reg, runtime->rate);
 }
 
-static int ac97_digital_trigger(struct snd_pcm_substream *substream,
-                               int cmd, struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       unsigned short vra;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_STOP:
-               vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
-               vra &= !0x04;
-               stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
-               break;
-       }
-       return 0;
-}
-
 static int stac9766_set_bias_level(struct snd_soc_codec *codec,
                                   enum snd_soc_bias_level level)
 {
@@ -315,7 +300,6 @@ static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
 
 static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
        .prepare = ac97_digital_prepare,
-       .trigger = ac97_digital_trigger,
 };
 
 struct snd_soc_dai stac9766_dai[] = {
index 81c57b5..a808675 100644 (file)
@@ -47,7 +47,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
 };
 
 #define WM8974_POWER1_BIASEN  0x08
-#define WM8974_POWER1_BUFIOEN 0x10
+#define WM8974_POWER1_BUFIOEN 0x04
 
 struct wm8974_priv {
        struct snd_soc_codec codec;
index c071f96..3c85c0f 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
-#include <linux/i2c/twl4030.h>
+#include <linux/i2c/twl.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -321,11 +321,11 @@ static int __init sdp3430_soc_init(void)
        *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
 
        /* Set TWL4030 GPIO6 as EXTMUTE signal */
-       twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
+       twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
                                                TWL4030_INTBR_PMBR1);
        pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03);
        pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02);
-       twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux,
+       twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux,
                                                TWL4030_INTBR_PMBR1);
 
        ret = platform_device_add(sdp3430_snd_device);
index 83b3dde..b2b3c2d 100644 (file)
@@ -354,7 +354,10 @@ static int cpio_mkfile(const char *name, const char *location,
                push_pad();
 
                if (size) {
-                       fwrite(filebuf, size, 1, stdout);
+                       if (fwrite(filebuf, size, 1, stdout) != 1) {
+                               fprintf(stderr, "writing filebuf failed\n");
+                               goto error;
+                       }
                        offset += size;
                        push_pad();
                }