summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--Documentation/dontdiff1
-rw-r--r--Documentation/hwmon/k10temp60
-rw-r--r--Documentation/kbuild/kbuild.txt14
-rw-r--r--Documentation/kbuild/kconfig.txt8
-rw-r--r--Kbuild4
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile96
-rw-r--r--arch/alpha/boot/bootp.c2
-rw-r--r--arch/alpha/boot/bootpz.c2
-rw-r--r--arch/alpha/boot/main.c2
-rw-r--r--arch/alpha/include/asm/asm-offsets.h1
-rw-r--r--arch/alpha/include/asm/fcntl.h2
-rw-r--r--arch/arm/Makefile14
-rw-r--r--arch/arm/common/dmabounce.c12
-rw-r--r--arch/arm/include/asm/asm-offsets.h1
-rw-r--r--arch/arm/include/asm/cacheflush.h17
-rw-r--r--arch/arm/include/asm/mach-types.h1
-rw-r--r--arch/arm/mach-kirkwood/Kconfig6
-rw-r--r--arch/arm/mach-kirkwood/Makefile1
-rw-r--r--arch/arm/mach-kirkwood/netspace_v2-setup.c325
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c2
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c2
-rwxr-xr-xarch/arm/mach-omap2/board-zoom-peripherals.c2
-rw-r--r--arch/arm/mach-omap2/serial.c7
-rw-r--r--arch/arm/mach-pxa/Kconfig3
-rw-r--r--arch/arm/mach-pxa/devices.c2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/spi.h2
-rw-r--r--arch/arm/mm/cache-fa.S11
-rw-r--r--arch/arm/mm/cache-l2x0.c93
-rw-r--r--arch/arm/mm/cache-v3.S9
-rw-r--r--arch/arm/mm/cache-v4.S9
-rw-r--r--arch/arm/mm/cache-v4wb.S11
-rw-r--r--arch/arm/mm/cache-v4wt.S11
-rw-r--r--arch/arm/mm/cache-v6.S11
-rw-r--r--arch/arm/mm/cache-v7.S13
-rw-r--r--arch/arm/mm/flush.c4
-rw-r--r--arch/arm/mm/highmem.c2
-rw-r--r--arch/arm/mm/nommu.c2
-rw-r--r--arch/arm/mm/proc-arm1020.S11
-rw-r--r--arch/arm/mm/proc-arm1020e.S11
-rw-r--r--arch/arm/mm/proc-arm1022.S11
-rw-r--r--arch/arm/mm/proc-arm1026.S11
-rw-r--r--arch/arm/mm/proc-arm920.S11
-rw-r--r--arch/arm/mm/proc-arm922.S11
-rw-r--r--arch/arm/mm/proc-arm925.S11
-rw-r--r--arch/arm/mm/proc-arm926.S11
-rw-r--r--arch/arm/mm/proc-arm940.S9
-rw-r--r--arch/arm/mm/proc-arm946.S11
-rw-r--r--arch/arm/mm/proc-feroceon.S15
-rw-r--r--arch/arm/mm/proc-mohawk.S11
-rw-r--r--arch/arm/mm/proc-syms.c3
-rw-r--r--arch/arm/mm/proc-v6.S5
-rw-r--r--arch/arm/mm/proc-xsc3.S11
-rw-r--r--arch/arm/mm/proc-xscale.S13
-rw-r--r--arch/arm/tools/Makefile2
-rw-r--r--arch/arm/tools/gen-mach-types2
-rw-r--r--arch/arm/tools/mach-types44
-rw-r--r--arch/avr32/include/asm/asm-offsets.h1
-rw-r--r--arch/blackfin/include/asm/asm-offsets.h1
-rw-r--r--arch/cris/arch-v32/kernel/head.S1
-rw-r--r--arch/cris/include/asm/asm-offsets.h1
-rw-r--r--arch/cris/kernel/asm-offsets.c1
-rw-r--r--arch/cris/kernel/vmlinux.lds.S1
-rw-r--r--arch/frv/include/asm/asm-offsets.h1
-rw-r--r--arch/frv/kernel/setup.c2
-rw-r--r--arch/h8300/include/asm/asm-offsets.h1
-rw-r--r--arch/ia64/Makefile2
-rw-r--r--arch/ia64/include/asm/asm-offsets.h1
-rw-r--r--arch/ia64/include/asm/irq.h2
-rw-r--r--arch/ia64/kernel/Makefile7
-rw-r--r--arch/ia64/kvm/asm-offsets.c1
-rw-r--r--arch/m68k/include/asm/asm-offsets.h1
-rw-r--r--arch/m68k/kernel/head.S2
-rw-r--r--arch/microblaze/include/asm/asm-offsets.h1
-rw-r--r--arch/mips/Kconfig119
-rw-r--r--arch/mips/Kconfig.debug59
-rw-r--r--arch/mips/Makefile57
-rw-r--r--arch/mips/ar7/platform.c2
-rw-r--r--arch/mips/basler/excite/Kconfig9
-rw-r--r--arch/mips/basler/excite/Makefile8
-rw-r--r--arch/mips/basler/excite/excite_device.c403
-rw-r--r--arch/mips/basler/excite/excite_iodev.c178
-rw-r--r--arch/mips/basler/excite/excite_iodev.h10
-rw-r--r--arch/mips/basler/excite/excite_irq.c122
-rw-r--r--arch/mips/basler/excite/excite_procfs.c92
-rw-r--r--arch/mips/basler/excite/excite_prom.c144
-rw-r--r--arch/mips/basler/excite/excite_setup.c302
-rw-r--r--arch/mips/bcm47xx/prom.c10
-rw-r--r--arch/mips/boot/Makefile8
-rw-r--r--arch/mips/boot/addinitrd.c131
-rw-r--r--arch/mips/boot/compressed/Makefile100
-rw-r--r--arch/mips/boot/compressed/dbg.c37
-rw-r--r--arch/mips/boot/compressed/decompress.c126
-rw-r--r--arch/mips/boot/compressed/dummy.c4
-rw-r--r--arch/mips/boot/compressed/head.S56
-rw-r--r--arch/mips/boot/compressed/ld.script150
-rw-r--r--arch/mips/boot/compressed/uart-16550.c43
-rw-r--r--arch/mips/cavium-octeon/Makefile2
-rw-r--r--arch/mips/cavium-octeon/cpu.c52
-rw-r--r--arch/mips/cavium-octeon/octeon-platform.c88
-rw-r--r--arch/mips/configs/ar7_defconfig4
-rw-r--r--arch/mips/configs/bcm47xx_defconfig3
-rw-r--r--arch/mips/configs/bcm63xx_defconfig3
-rw-r--r--arch/mips/configs/bigsur_defconfig3
-rw-r--r--arch/mips/configs/capcella_defconfig3
-rw-r--r--arch/mips/configs/cavium-octeon_defconfig4
-rw-r--r--arch/mips/configs/cobalt_defconfig3
-rw-r--r--arch/mips/configs/db1000_defconfig3
-rw-r--r--arch/mips/configs/db1100_defconfig3
-rw-r--r--arch/mips/configs/db1200_defconfig3
-rw-r--r--arch/mips/configs/db1500_defconfig3
-rw-r--r--arch/mips/configs/db1550_defconfig3
-rw-r--r--arch/mips/configs/decstation_defconfig3
-rw-r--r--arch/mips/configs/e55_defconfig3
-rw-r--r--arch/mips/configs/excite_defconfig1335
-rw-r--r--arch/mips/configs/fuloong2e_defconfig96
-rw-r--r--arch/mips/configs/ip22_defconfig3
-rw-r--r--arch/mips/configs/ip27_defconfig3
-rw-r--r--arch/mips/configs/ip28_defconfig3
-rw-r--r--arch/mips/configs/ip32_defconfig3
-rw-r--r--arch/mips/configs/jazz_defconfig3
-rw-r--r--arch/mips/configs/jmr3927_defconfig3
-rw-r--r--arch/mips/configs/lasat_defconfig3
-rw-r--r--arch/mips/configs/lemote2f_defconfig1835
-rw-r--r--arch/mips/configs/malta_defconfig3
-rw-r--r--arch/mips/configs/markeins_defconfig3
-rw-r--r--arch/mips/configs/mipssim_defconfig3
-rw-r--r--arch/mips/configs/mpc30x_defconfig3
-rw-r--r--arch/mips/configs/msp71xx_defconfig3
-rw-r--r--arch/mips/configs/mtx1_defconfig3
-rw-r--r--arch/mips/configs/pb1100_defconfig3
-rw-r--r--arch/mips/configs/pb1500_defconfig3
-rw-r--r--arch/mips/configs/pb1550_defconfig3
-rw-r--r--arch/mips/configs/pnx8335-stb225_defconfig3
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig3
-rw-r--r--arch/mips/configs/pnx8550-stb810_defconfig3
-rw-r--r--arch/mips/configs/powertv_defconfig1550
-rw-r--r--arch/mips/configs/rb532_defconfig3
-rw-r--r--arch/mips/configs/rbtx49xx_defconfig4
-rw-r--r--arch/mips/configs/rm200_defconfig3
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig3
-rw-r--r--arch/mips/configs/tb0219_defconfig3
-rw-r--r--arch/mips/configs/tb0226_defconfig3
-rw-r--r--arch/mips/configs/tb0287_defconfig3
-rw-r--r--arch/mips/configs/workpad_defconfig3
-rw-r--r--arch/mips/configs/wrppmc_defconfig3
-rw-r--r--arch/mips/configs/yosemite_defconfig3
-rw-r--r--arch/mips/fw/arc/cmdline.c5
-rw-r--r--arch/mips/include/asm/asm-offsets.h1
-rw-r--r--arch/mips/include/asm/bootinfo.h8
-rw-r--r--arch/mips/include/asm/clock.h64
-rw-r--r--arch/mips/include/asm/cop2.h23
-rw-r--r--arch/mips/include/asm/cpu.h2
-rw-r--r--arch/mips/include/asm/fcntl.h2
-rw-r--r--arch/mips/include/asm/fpu.h8
-rw-r--r--arch/mips/include/asm/fpu_emulator.h24
-rw-r--r--arch/mips/include/asm/ftrace.h91
-rw-r--r--arch/mips/include/asm/irq.h29
-rw-r--r--arch/mips/include/asm/mach-excite/cpu-feature-overrides.h48
-rw-r--r--arch/mips/include/asm/mach-excite/excite.h154
-rw-r--r--arch/mips/include/asm/mach-excite/excite_fpga.h80
-rw-r--r--arch/mips/include/asm/mach-excite/excite_nandflash.h7
-rw-r--r--arch/mips/include/asm/mach-excite/rm9k_eth.h23
-rw-r--r--arch/mips/include/asm/mach-excite/rm9k_wdt.h12
-rw-r--r--arch/mips/include/asm/mach-excite/rm9k_xicap.h16
-rw-r--r--arch/mips/include/asm/mach-loongson/cs5536/cs5536.h305
-rw-r--r--arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h35
-rw-r--r--arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h153
-rw-r--r--arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h31
-rw-r--r--arch/mips/include/asm/mach-loongson/dma-coherence.h4
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h290
-rw-r--r--arch/mips/include/asm/mach-loongson/machine.h9
-rw-r--r--arch/mips/include/asm/mach-loongson/mem.h27
-rw-r--r--arch/mips/include/asm/mach-loongson/pci.h34
-rw-r--r--arch/mips/include/asm/mach-powertv/asic.h107
-rw-r--r--arch/mips/include/asm/mach-powertv/asic_regs.h155
-rw-r--r--arch/mips/include/asm/mach-powertv/dma-coherence.h119
-rw-r--r--arch/mips/include/asm/mach-powertv/interrupts.h254
-rw-r--r--arch/mips/include/asm/mach-powertv/ioremap.h90
-rw-r--r--arch/mips/include/asm/mach-powertv/irq.h25
-rw-r--r--arch/mips/include/asm/mach-powertv/powertv-clock.h29
-rw-r--r--arch/mips/include/asm/mach-powertv/war.h (renamed from arch/mips/include/asm/mach-excite/war.h)19
-rw-r--r--arch/mips/include/asm/mips-boards/bonito64.h5
-rw-r--r--arch/mips/include/asm/mmu_context.h29
-rw-r--r--arch/mips/include/asm/octeon/cvmx-agl-defs.h1194
-rw-r--r--arch/mips/include/asm/octeon/cvmx-mixx-defs.h248
-rw-r--r--arch/mips/include/asm/octeon/cvmx-smix-defs.h178
-rw-r--r--arch/mips/include/asm/octeon/octeon.h1
-rw-r--r--arch/mips/include/asm/pgtable.h13
-rw-r--r--arch/mips/include/asm/sgialib.h3
-rw-r--r--arch/mips/include/asm/stackframe.h40
-rw-r--r--arch/mips/kernel/Makefile14
-rw-r--r--arch/mips/kernel/cpu-probe.c2
-rw-r--r--arch/mips/kernel/cpufreq/Kconfig41
-rw-r--r--arch/mips/kernel/cpufreq/Makefile5
-rw-r--r--arch/mips/kernel/cpufreq/loongson2_clock.c166
-rw-r--r--arch/mips/kernel/cpufreq/loongson2_cpufreq.c227
-rw-r--r--arch/mips/kernel/csrc-powertv.c180
-rw-r--r--arch/mips/kernel/ftrace.c275
-rw-r--r--arch/mips/kernel/irq.c30
-rw-r--r--arch/mips/kernel/mcount.S189
-rw-r--r--arch/mips/kernel/mips_ksyms.c5
-rw-r--r--arch/mips/kernel/setup.c44
-rw-r--r--arch/mips/kernel/signal.c46
-rw-r--r--arch/mips/kernel/signal32.c24
-rw-r--r--arch/mips/kernel/smp.c3
-rw-r--r--arch/mips/kernel/smtc.c21
-rw-r--r--arch/mips/kernel/traps.c136
-rw-r--r--arch/mips/kernel/unaligned.c25
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/lasat/picvue_proc.c113
-rw-r--r--arch/mips/lasat/prom.c4
-rw-r--r--arch/mips/lasat/sysctl.c2
-rw-r--r--arch/mips/loongson/Kconfig108
-rw-r--r--arch/mips/loongson/Makefile6
-rw-r--r--arch/mips/loongson/common/Makefile18
-rw-r--r--arch/mips/loongson/common/bonito-irq.c13
-rw-r--r--arch/mips/loongson/common/cmdline.c4
-rw-r--r--arch/mips/loongson/common/cs5536/Makefile13
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_acc.c140
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ehci.c158
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ide.c179
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_isa.c316
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_mfgpt.c217
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ohci.c147
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_pci.c87
-rw-r--r--arch/mips/loongson/common/early_printk.c17
-rw-r--r--arch/mips/loongson/common/env.c3
-rw-r--r--arch/mips/loongson/common/init.c19
-rw-r--r--arch/mips/loongson/common/irq.c12
-rw-r--r--arch/mips/loongson/common/machtype.c25
-rw-r--r--arch/mips/loongson/common/mem.c91
-rw-r--r--arch/mips/loongson/common/pci.c20
-rw-r--r--arch/mips/loongson/common/platform.c30
-rw-r--r--arch/mips/loongson/common/pm.c161
-rw-r--r--arch/mips/loongson/common/reset.c2
-rw-r--r--arch/mips/loongson/common/serial.c76
-rw-r--r--arch/mips/loongson/common/time.c3
-rw-r--r--arch/mips/loongson/common/uart_base.c45
-rw-r--r--arch/mips/loongson/fuloong-2e/irq.c4
-rw-r--r--arch/mips/loongson/fuloong-2e/reset.c4
-rw-r--r--arch/mips/loongson/lemote-2f/Makefile11
-rw-r--r--arch/mips/loongson/lemote-2f/ec_kb3310b.c130
-rw-r--r--arch/mips/loongson/lemote-2f/ec_kb3310b.h188
-rw-r--r--arch/mips/loongson/lemote-2f/irq.c134
-rw-r--r--arch/mips/loongson/lemote-2f/pm.c149
-rw-r--r--arch/mips/loongson/lemote-2f/reset.c159
-rw-r--r--arch/mips/math-emu/cp1emu.c102
-rw-r--r--arch/mips/math-emu/dsemul.c4
-rw-r--r--arch/mips/mipssim/Makefile3
-rw-r--r--arch/mips/mipssim/sim_setup.c1
-rw-r--r--arch/mips/mm/cerr-sb1.c7
-rw-r--r--arch/mips/mm/init.c2
-rw-r--r--arch/mips/mm/tlbex.c28
-rw-r--r--arch/mips/mm/uasm.c16
-rw-r--r--arch/mips/mm/uasm.h7
-rw-r--r--arch/mips/mti-malta/malta-memory.c2
-rw-r--r--arch/mips/nxp/pnx833x/common/interrupts.c4
-rw-r--r--arch/mips/oprofile/op_model_loongson2.c5
-rw-r--r--arch/mips/pci/Makefile4
-rw-r--r--arch/mips/pci/fixup-excite.c36
-rw-r--r--arch/mips/pci/fixup-fuloong2e.c5
-rw-r--r--arch/mips/pci/fixup-lemote2f.c160
-rw-r--r--arch/mips/pci/ops-bonito64.c7
-rw-r--r--arch/mips/pci/ops-loongson2.c208
-rw-r--r--arch/mips/pci/pci-excite.c149
-rw-r--r--arch/mips/powertv/Kconfig21
-rw-r--r--arch/mips/powertv/Makefile28
-rw-r--r--arch/mips/powertv/asic/Kconfig28
-rw-r--r--arch/mips/powertv/asic/Makefile23
-rw-r--r--arch/mips/powertv/asic/asic-calliope.c98
-rw-r--r--arch/mips/powertv/asic/asic-cronus.c98
-rw-r--r--arch/mips/powertv/asic/asic-zeus.c98
-rw-r--r--arch/mips/powertv/asic/asic_devices.c787
-rw-r--r--arch/mips/powertv/asic/asic_int.c125
-rw-r--r--arch/mips/powertv/asic/irq_asic.c116
-rw-r--r--arch/mips/powertv/asic/prealloc-calliope.c620
-rw-r--r--arch/mips/powertv/asic/prealloc-cronus.c608
-rw-r--r--arch/mips/powertv/asic/prealloc-cronuslite.c290
-rw-r--r--arch/mips/powertv/asic/prealloc-zeus.c459
-rw-r--r--arch/mips/powertv/cmdline.c52
-rw-r--r--arch/mips/powertv/init.c128
-rw-r--r--arch/mips/powertv/init.h28
-rw-r--r--arch/mips/powertv/memory.c186
-rw-r--r--arch/mips/powertv/pci/Makefile21
-rw-r--r--arch/mips/powertv/pci/fixup-powertv.c36
-rw-r--r--arch/mips/powertv/pci/powertv-pci.h31
-rw-r--r--arch/mips/powertv/powertv-clock.h26
-rw-r--r--arch/mips/powertv/powertv_setup.c351
-rw-r--r--arch/mips/powertv/reset.c65
-rw-r--r--arch/mips/powertv/reset.h26
-rw-r--r--arch/mips/powertv/time.c (renamed from arch/mips/mipssim/sim_cmdline.c)21
-rw-r--r--arch/mips/rb532/prom.c4
-rw-r--r--arch/mips/sgi-ip22/ip22-eisa.c4
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c3
-rw-r--r--arch/mips/sgi-ip22/ip22-setup.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c3
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c2
-rw-r--r--arch/mips/sibyte/common/cfe.c4
-rw-r--r--arch/mips/sni/a20r.c2
-rw-r--r--arch/mips/sni/pcimt.c2
-rw-r--r--arch/mips/sni/pcit.c2
-rw-r--r--arch/mips/sni/rm200.c2
-rw-r--r--arch/mips/sni/setup.c2
-rw-r--r--arch/mips/txx9/generic/setup.c4
-rw-r--r--arch/mn10300/include/asm/asm-offsets.h1
-rw-r--r--arch/parisc/include/asm/asm-offsets.h1
-rw-r--r--arch/powerpc/include/asm/asm-offsets.h1
-rw-r--r--arch/powerpc/platforms/52xx/efika.c2
-rw-r--r--arch/powerpc/platforms/amigaone/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile6
-rw-r--r--arch/powerpc/platforms/chrp/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c2
-rw-r--r--arch/s390/include/asm/asm-offsets.h1
-rw-r--r--arch/score/include/asm/asm-offsets.h1
-rw-r--r--arch/score/include/asm/cacheflush.h4
-rw-r--r--arch/score/include/asm/delay.h2
-rw-r--r--arch/score/include/asm/page.h2
-rw-r--r--arch/score/kernel/setup.c1
-rw-r--r--arch/score/mm/cache.c26
-rw-r--r--arch/score/mm/init.c5
-rw-r--r--arch/sh/Makefile10
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c2
-rw-r--r--arch/sh/include/asm/.gitignore1
-rw-r--r--arch/sh/include/asm/asm-offsets.h1
-rw-r--r--arch/sh/include/asm/machvec.h2
-rw-r--r--arch/sh/tools/Makefile4
-rw-r--r--arch/sh/tools/gen-mach-types2
-rw-r--r--arch/sparc/include/asm/asm-offsets.h1
-rw-r--r--arch/sparc/include/asm/fcntl.h2
-rw-r--r--arch/um/Makefile2
-rw-r--r--arch/um/include/asm/asm-offsets.h1
-rw-r--r--arch/x86/boot/header.S2
-rw-r--r--arch/x86/boot/version.c4
-rw-r--r--arch/x86/include/asm/asm-offsets.h1
-rw-r--r--arch/x86/kernel/ptrace.c16
-rw-r--r--arch/xtensa/include/asm/asm-offsets.h1
-rw-r--r--drivers/accessibility/braille/braille_console.c1
-rw-r--r--drivers/hid/hid-lg.h2
-rw-r--r--drivers/hwmon/Kconfig37
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/k10temp.c197
-rw-r--r--drivers/hwmon/lis3lv02d_i2c.c183
-rw-r--r--drivers/hwmon/sht15.c6
-rw-r--r--drivers/hwmon/smsc47m1.c153
-rw-r--r--drivers/hwmon/via-cputemp.c356
-rw-r--r--drivers/hwmon/w83627hf.c2
-rw-r--r--drivers/leds/Kconfig33
-rw-r--r--drivers/leds/Makefile4
-rw-r--r--drivers/leds/leds-adp5520.c230
-rw-r--r--drivers/leds/leds-alix2.c115
-rw-r--r--drivers/leds/leds-cobalt-qube.c4
-rw-r--r--drivers/leds/leds-cobalt-raq.c2
-rw-r--r--drivers/leds/leds-lt3593.c217
-rw-r--r--drivers/leds/leds-pwm.c5
-rw-r--r--drivers/leds/leds-regulator.c242
-rw-r--r--drivers/leds/leds-ss4200.c556
-rw-r--r--drivers/message/fusion/mptbase.c6
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/enclosure.c1
-rw-r--r--drivers/mmc/core/sdio.c5
-rw-r--r--drivers/mmc/core/sdio_bus.c7
-rw-r--r--drivers/mmc/host/Kconfig37
-rw-r--r--drivers/mmc/host/Makefile6
-rw-r--r--drivers/mmc/host/sdhci-of-core.c (renamed from drivers/mmc/host/sdhci-of.c)143
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c143
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c65
-rw-r--r--drivers/mmc/host/sdhci-of.h42
-rw-r--r--drivers/mmc/host/sdhci.h4
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c13
-rw-r--r--drivers/mtd/nand/Kconfig8
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/excite_nandflash.c248
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/octeon/Kconfig10
-rw-r--r--drivers/net/octeon/Makefile2
-rw-r--r--drivers/net/octeon/octeon_mgmt.c1176
-rw-r--r--drivers/net/phy/Kconfig11
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/mdio-octeon.c180
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/pcmcia/pxa2xx_base.c6
-rw-r--r--drivers/platform/x86/compal-laptop.c1
-rw-r--r--drivers/regulator/88pm8607.c685
-rw-r--r--drivers/regulator/Kconfig13
-rw-r--r--drivers/regulator/Makefile4
-rw-r--r--drivers/regulator/ab3100.c33
-rw-r--r--drivers/regulator/core.c248
-rw-r--r--drivers/regulator/da903x.c2
-rw-r--r--drivers/regulator/lp3971.c4
-rw-r--r--drivers/regulator/max8660.c510
-rw-r--r--drivers/regulator/mc13783-regulator.c245
-rw-r--r--drivers/regulator/mc13783.c410
-rw-r--r--drivers/regulator/twl-regulator.c147
-rw-r--r--drivers/regulator/wm831x-dcdc.c207
-rw-r--r--drivers/regulator/wm831x-ldo.c2
-rw-r--r--drivers/rtc/rtc-cmos.c3
-rw-r--r--drivers/rtc/rtc-ds1305.c2
-rw-r--r--drivers/rtc/rtc-ds1307.c2
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/scsi/3w-9xxx.c11
-rw-r--r--drivers/scsi/Kconfig10
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c12
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h1
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c51
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c16
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.c24
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.c4
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c2
-rw-r--r--drivers/scsi/fcoe/fcoe.c135
-rw-r--r--drivers/scsi/hpsa.c3531
-rw-r--r--drivers/scsi/hpsa.h273
-rw-r--r--drivers/scsi/hpsa_cmd.h326
-rw-r--r--drivers/scsi/ipr.c1
-rw-r--r--drivers/scsi/libfc/fc_fcp.c65
-rw-r--r--drivers/scsi/libfc/fc_lport.c7
-rw-r--r--drivers/scsi/libfc/fc_rport.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c16
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c14
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c5
-rw-r--r--drivers/scsi/mvsas/mv_init.c1
-rw-r--r--drivers/scsi/osd/osd_initiator.c88
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.h10
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c149
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.h3
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c19
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c57
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h32
-rw-r--r--drivers/scsi/pmcraid.c34
-rw-r--r--drivers/scsi/pmcraid.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c103
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c75
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_lib.c1
-rw-r--r--drivers/scsi/scsi_transport_fc.c17
-rw-r--r--drivers/scsi/sd.c107
-rw-r--r--drivers/scsi/sd.h2
-rw-r--r--drivers/scsi/st.c23
-rw-r--r--drivers/scsi/st.h1
-rw-r--r--drivers/spi/Kconfig28
-rw-r--r--drivers/spi/Makefile10
-rw-r--r--drivers/spi/atmel_spi.c6
-rw-r--r--drivers/spi/dw_spi.c944
-rw-r--r--drivers/spi/dw_spi_pci.c169
-rw-r--r--drivers/spi/spi_bfin5xx.c2
-rw-r--r--drivers/spi/spi_mpc8xxx.c2
-rw-r--r--drivers/spi/spi_s3c24xx.c244
-rw-r--r--drivers/spi/spi_s3c24xx_fiq.S116
-rw-r--r--drivers/spi/spi_s3c24xx_fiq.h26
-rw-r--r--drivers/spi/spi_s3c64xx.c1196
-rw-r--r--drivers/spi/spi_sh_sci.c2
-rw-r--r--drivers/spi/spi_txx9.c6
-rw-r--r--drivers/spi/spidev.c18
-rw-r--r--drivers/staging/iio/ring_sw.h1
-rw-r--r--drivers/staging/octeon/Kconfig3
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c204
-rw-r--r--drivers/staging/octeon/ethernet-mdio.h2
-rw-r--r--drivers/staging/octeon/ethernet-proc.c112
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c52
-rw-r--r--drivers/staging/octeon/ethernet-sgmii.c2
-rw-r--r--drivers/staging/octeon/ethernet-xaui.c2
-rw-r--r--drivers/staging/octeon/ethernet.c23
-rw-r--r--drivers/staging/octeon/octeon-ethernet.h6
-rw-r--r--drivers/staging/panel/panel.c2
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/video/atafb.c3
-rw-r--r--drivers/video/backlight/adp5520_bl.c2
-rw-r--r--drivers/video/backlight/adx_bl.c2
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c2
-rw-r--r--drivers/video/backlight/backlight.c2
-rw-r--r--drivers/video/backlight/corgi_lcd.c2
-rw-r--r--drivers/video/backlight/cr_bllcd.c4
-rw-r--r--drivers/video/backlight/da903x_bl.c2
-rw-r--r--drivers/video/backlight/generic_bl.c2
-rw-r--r--drivers/video/backlight/hp680_bl.c2
-rw-r--r--drivers/video/backlight/jornada720_bl.c2
-rw-r--r--drivers/video/backlight/kb3886_bl.c2
-rw-r--r--drivers/video/backlight/locomolcd.c2
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c20
-rw-r--r--drivers/video/backlight/omap1_bl.c2
-rw-r--r--drivers/video/backlight/progear_bl.c2
-rw-r--r--drivers/video/backlight/pwm_bl.c11
-rw-r--r--drivers/video/backlight/tosa_bl.c2
-rw-r--r--drivers/video/backlight/wm831x_bl.c2
-rw-r--r--drivers/video/omap/lcd_ldp.c4
-rw-r--r--drivers/video/omap/lcd_omap2evm.c10
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c2
-rw-r--r--drivers/video/omap/lcd_omap3evm.c10
-rw-r--r--drivers/video/omap/lcd_overo.c2
-rw-r--r--drivers/video/via/viafbdev.c4
-rw-r--r--drivers/watchdog/Kconfig10
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/rm9k_wdt.c419
-rw-r--r--fs/Kconfig4
-rw-r--r--fs/anon_inodes.c17
-rw-r--r--fs/binfmt_aout.c13
-rw-r--r--fs/binfmt_elf.c24
-rw-r--r--fs/binfmt_elf_fdpic.c29
-rw-r--r--fs/binfmt_flat.c6
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/btrfs/Kconfig1
-rw-r--r--fs/btrfs/acl.c23
-rw-r--r--fs/btrfs/btrfs_inode.h5
-rw-r--r--fs/btrfs/ctree.c229
-rw-r--r--fs/btrfs/ctree.h40
-rw-r--r--fs/btrfs/dir-item.c19
-rw-r--r--fs/btrfs/disk-io.c27
-rw-r--r--fs/btrfs/extent-tree.c72
-rw-r--r--fs/btrfs/file.c669
-rw-r--r--fs/btrfs/inode.c567
-rw-r--r--fs/btrfs/ioctl.c34
-rw-r--r--fs/btrfs/ordered-data.c115
-rw-r--r--fs/btrfs/ordered-data.h5
-rw-r--r--fs/btrfs/relocation.c38
-rw-r--r--fs/btrfs/super.c15
-rw-r--r--fs/btrfs/transaction.c44
-rw-r--r--fs/btrfs/transaction.h6
-rw-r--r--fs/btrfs/tree-log.c86
-rw-r--r--fs/btrfs/volumes.c2
-rw-r--r--fs/btrfs/xattr.c80
-rw-r--r--fs/btrfs/xattr.h9
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/ecryptfs/dentry.c2
-rw-r--r--fs/ecryptfs/inode.c6
-rw-r--r--fs/ecryptfs/main.c2
-rw-r--r--fs/exec.c40
-rw-r--r--fs/ext4/Kconfig1
-rw-r--r--fs/gfs2/Kconfig1
-rw-r--r--fs/gfs2/inode.c2
-rw-r--r--fs/inode.c26
-rw-r--r--fs/jbd/Kconfig1
-rw-r--r--fs/jbd2/Kconfig1
-rw-r--r--fs/jfs/jfs_txnmgr.c2
-rw-r--r--fs/namei.c2
-rw-r--r--fs/namespace.c3
-rw-r--r--fs/nfs/super.c8
-rw-r--r--fs/nilfs2/Kconfig1
-rw-r--r--fs/ntfs/inode.c6
-rw-r--r--fs/pipe.c18
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/reiserfs/Kconfig1
-rw-r--r--fs/reiserfs/inode.c18
-rw-r--r--fs/stack.c71
-rw-r--r--fs/sync.c59
-rw-r--r--fs/ubifs/file.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c2
-rw-r--r--fs/xfs/xfs_iget.c4
-rw-r--r--include/asm-generic/fcntl.h2
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/backlight.h12
-rw-r--r--include/linux/binfmts.h10
-rw-r--r--include/linux/enclosure.h2
-rw-r--r--include/linux/fs.h40
-rw-r--r--include/linux/fs_stack.h6
-rw-r--r--include/linux/init_task.h8
-rw-r--r--include/linux/kmemleak.h6
-rw-r--r--include/linux/leds-lp3944.h3
-rw-r--r--include/linux/leds-pca9532.h2
-rw-r--r--include/linux/leds-regulator.h46
-rw-r--r--include/linux/mfd/wm831x/pdata.h17
-rw-r--r--include/linux/mmdebug.h2
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--include/linux/mnt_namespace.h1
-rw-r--r--include/linux/page-flags.h2
-rw-r--r--include/linux/pwm_backlight.h2
-rw-r--r--include/linux/regulator/consumer.h2
-rw-r--r--include/linux/regulator/machine.h6
-rw-r--r--include/linux/regulator/max8660.h57
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/security.h7
-rw-r--r--include/linux/spi/dw_spi.h212
-rw-r--r--include/linux/vermagic.h2
-rw-r--r--include/linux/vt.h4
-rw-r--r--include/linux/writeback.h3
-rw-r--r--include/scsi/osd_initiator.h5
-rw-r--r--init/Makefile8
-rw-r--r--init/version.c4
-rw-r--r--kernel/bounds.c2
-rw-r--r--kernel/exit.c36
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/kexec.c2
-rw-r--r--kernel/module.c13
-rw-r--r--kernel/printk.c4
-rw-r--r--kernel/sysctl.c4
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--lib/Kconfig.debug1
-rw-r--r--lib/vsprintf.c13
-rw-r--r--mm/Kconfig1
-rw-r--r--mm/kmemleak.c188
-rw-r--r--mm/readahead.c12
-rw-r--r--mm/shmem.c2
-rw-r--r--mm/slab.c10
-rw-r--r--net/socket.c19
-rw-r--r--scripts/Kbuild.include6
-rw-r--r--scripts/Makefile.build1
-rw-r--r--scripts/Makefile.lib2
-rw-r--r--scripts/Makefile.modbuiltin55
-rw-r--r--scripts/basic/fixdep.c10
-rw-r--r--scripts/genksyms/keywords.c_shipped191
-rw-r--r--scripts/genksyms/keywords.gperf2
-rwxr-xr-xscripts/headers.sh2
-rw-r--r--scripts/kconfig/Makefile1
-rw-r--r--scripts/kconfig/confdata.c24
-rwxr-xr-xscripts/mkcompile_h2
-rw-r--r--scripts/mod/modpost.c2
-rw-r--r--scripts/package/Makefile20
-rw-r--r--scripts/package/buildtar6
-rwxr-xr-xscripts/recordmcount.pl58
-rwxr-xr-xscripts/tags.sh8
-rw-r--r--scripts/unifdef.c341
-rw-r--r--security/Makefile3
-rw-r--r--security/keys/keyctl.c12
-rw-r--r--security/min_addr.c2
-rw-r--r--sound/soc/omap/sdp3430.c6
-rw-r--r--usr/gen_init_cpio.c5
627 files changed, 33748 insertions, 8011 deletions
diff --git a/.gitignore b/.gitignore
index 946c7ec5c922..fb2190c61af0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index e151b2a36267..3ad6acead949 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -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
index 000000000000..a7a18d453a51
--- /dev/null
+++ b/Documentation/hwmon/k10temp
@@ -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.
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index bb3bf38f03da..6f8c1cabbc5d 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -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
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
index 849b5e56d06f..49efae703979 100644
--- a/Documentation/kbuild/kconfig.txt
+++ b/Documentation/kbuild/kconfig.txt
@@ -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 f056b4feee51..e3737ad72b5a 100644
--- 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)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0699782f8c5b..efd2ef2c2660 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/Makefile b/Makefile
index 33d4732a6c4a..8491b21b5537 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
index 3af21c789339..3c8d1b25c661 100644
--- a/arch/alpha/boot/bootp.c
+++ b/arch/alpha/boot/bootp.c
@@ -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>
diff --git a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c
index 1036b515e20c..ade3f129dc27 100644
--- a/arch/alpha/boot/bootpz.c
+++ b/arch/alpha/boot/bootpz.c
@@ -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>
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
index 89f3be071ae5..644b7db55438 100644
--- a/arch/alpha/boot/main.c
+++ b/arch/alpha/boot/main.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/alpha/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h
index 21b1117a0c61..70145cbb21cb 100644
--- a/arch/alpha/include/asm/fcntl.h
+++ b/arch/alpha/include/asm/fcntl.h
@@ -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
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fa0cdab2e1d3..e9da08483b3c 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -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)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5a375e5fef21..bc90364a96c7 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/arm/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 73eceb87e588..730aefcfbee3 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -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
index 000000000000..948178cc6ba8
--- /dev/null
+++ b/arch/arm/include/asm/mach-types.h
@@ -0,0 +1 @@
+#include <generated/mach-types.h>
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 8bf09ae5b347..f6c6196a51fa 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -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
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 9f2f67b2b63d..d4d7f53b0fb9 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -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
index 000000000000..9a064065bebe
--- /dev/null
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -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
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 76c11ee113e9..10eafa70a909 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -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"
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 1591aae64500..2626a9f8a73a 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -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>
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 44239e3ec02e..117b8fd7e3a6 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -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>
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 18913e96e34d..34de17851572 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -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>
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index c9e5ebb4d91d..fe3d22cb2457 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -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>
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 17f3c91231db..acafdbc8aa16 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -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>
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 258794db488f..8dd277c36661 100755
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -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>
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 39b797bc14d6..19805a7de06c 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -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;
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index e6d8e10ae5d1..8a0837ea0294 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -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"
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 3395463bb5a6..8e10db148f1b 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -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>
diff --git a/arch/arm/mach-s3c2410/include/mach/spi.h b/arch/arm/mach-s3c2410/include/mach/spi.h
index 193b39d654ed..4d9588373aa5 100644
--- a/arch/arm/mach-s3c2410/include/mach/spi.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi.h
@@ -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);
};
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index b63a8f7b95cf..a89444a3c016 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -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
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 747f9a9021bb..cb8fc6573b1b 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -28,69 +28,120 @@
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)
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index 8a4abebc478a..2a482731ea36 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -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
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index 3668611cb400..5c7da3e372e9 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -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
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 2ebc1b3bf856..3dbedf1ec0e7 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -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
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index c54fa2cc40e6..b3b7410270b4 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -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
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 295e25dd6381..4ba0a24ce6f5 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -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
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index e1bd9759617f..9073db849fb4 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -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
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 329594e760cd..6f3a4b7a3b82 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -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);
}
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index 30f82fb5918c..2be1ec7c1b41 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -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);
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 900811cc9130..374a8311bc84 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -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);
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index d9fb4b98c49f..8012e24282b2 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -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
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 7453b75dcea5..41fe25d234f5 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -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
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 8eb72d75a8b6..20a5b1b31a70 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -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
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 3b59f0d67139..96aedb10fcc4 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -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
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 2b7c197cc58d..471669e2d7cb 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -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
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 06a1aa4e3398..ee111b00fa41 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -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
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index cb53435a85ae..8deb5bde58e4 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -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
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 1c4848704bb3..64db6e275a44 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -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
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 5b0f8464c8f2..8196b9f401fb 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -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
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 40c0449a139b..9a951239c86c 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -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
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index d0d7795200fc..dbc39383e66a 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -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
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 52b5fd74fbb3..9674d36cc97d 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -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
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index ac5c80062b70..3e6210b4d6d4 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -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
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 5485c821101c..395cc90c6613 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -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 | \
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index fab134e29826..96456f548798 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -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
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index f056c283682d..93df47265f2d 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -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
diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
index 1dbaa29ac4d7..635cb1865e4d 100644
--- a/arch/arm/tools/Makefile
+++ b/arch/arm/tools/Makefile
@@ -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; }
diff --git a/arch/arm/tools/gen-mach-types b/arch/arm/tools/gen-mach-types
index ce319ef64bc1..04fef71d7be9 100644
--- a/arch/arm/tools/gen-mach-types
+++ b/arch/arm/tools/gen-mach-types
@@ -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 }
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 07b976da6174..c3a74ce24ef6 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/avr32/include/asm/asm-offsets.h
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/blackfin/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 3db478eb5155..76266f80a5f1 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/cris/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/cris/kernel/asm-offsets.c b/arch/cris/kernel/asm-offsets.c
index ddd6fbbe75de..dd7b8e983221 100644
--- a/arch/cris/kernel/asm-offsets.c
+++ b/arch/cris/kernel/asm-offsets.c
@@ -1,6 +1,5 @@
#include <linux/sched.h>
#include <asm/thread_info.h>
-#include <linux/autoconf.h>
/*
* Generate definitions needed by assembly language modules.
diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S
index bbfda67d2907..d49d17d2a14f 100644
--- a/arch/cris/kernel/vmlinux.lds.S
+++ b/arch/cris/kernel/vmlinux.lds.S
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/frv/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 55e4fab7c0bc..75cf7f4b2fa8 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/h8300/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index e7cbaa02cd0b..475e2725fbde 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/ia64/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/ia64/include/asm/irq.h b/arch/ia64/include/asm/irq.h
index 5282546cdf82..91b920fd7d53 100644
--- a/arch/ia64/include/asm/irq.h
+++ b/arch/ia64/include/asm/irq.h
@@ -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)
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 6b7edcab0cb5..2a75e937ae8d 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -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
#
diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c
index 0c3564a7a033..9324c875caf5 100644
--- a/arch/ia64/kvm/asm-offsets.c
+++ b/arch/ia64/kvm/asm-offsets.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/m68k/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 86edb5fbcfc3..ef54128baa0b 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -196,7 +196,7 @@
* 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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/microblaze/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fd7620f025fa..9541171f1220 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -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"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 364ca8938807..d2b88a0be519 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -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"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 77f5021218d3..1893efd43fca 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -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
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 835f3f0319ca..85169c08d8dc 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -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
index ba506075608b..000000000000
--- a/arch/mips/basler/excite/Kconfig
+++ /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
index cff29cf46d03..000000000000
--- a/arch/mips/basler/excite/Makefile
+++ /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
index e00bc2d7f301..000000000000
--- a/arch/mips/basler/excite/excite_device.c
+++ /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
index 938b1d0b7652..000000000000
--- a/arch/mips/basler/excite/excite_iodev.c
+++ /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
index cbfbb5d2ee62..000000000000
--- a/arch/mips/basler/excite/excite_iodev.h
+++ /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
index 934e0a6b1011..000000000000
--- a/arch/mips/basler/excite/excite_irq.c
+++ /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
index 08923e6825b5..000000000000
--- a/arch/mips/basler/excite/excite_procfs.c
+++ /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
index 68d8bc597e34..000000000000
--- a/arch/mips/basler/excite/excite_prom.c
+++ /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
index d66b3b8edf2a..000000000000
--- a/arch/mips/basler/excite/excite_setup.c
+++ /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);
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index fb284c3b2cff..c51405e57921 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -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]);
}
}
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index 2a209d74f0b4..094bc84765a3 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -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
index b5b3febc10cc..000000000000
--- a/arch/mips/boot/addinitrd.c
+++ /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
index 000000000000..e27f40bbd4e5
--- /dev/null
+++ b/arch/mips/boot/compressed/Makefile
@@ -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
index 000000000000..ff4dc7a33a9f
--- /dev/null
+++ b/arch/mips/boot/compressed/dbg.c
@@ -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
index 000000000000..67330c2f7318
--- /dev/null
+++ b/arch/mips/boot/compressed/decompress.c
@@ -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
index 000000000000..31dbf45bf99c
--- /dev/null
+++ b/arch/mips/boot/compressed/dummy.c
@@ -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
index 000000000000..4e65a8420bee
--- /dev/null
+++ b/arch/mips/boot/compressed/head.S
@@ -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
index 000000000000..29e9f4c0d5d8
--- /dev/null
+++ b/arch/mips/boot/compressed/ld.script
@@ -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
index 000000000000..c9caaf4fbf60
--- /dev/null
+++ b/arch/mips/boot/compressed/uart-16550.c
@@ -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);
+}
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 139436280520..3e9876317e61 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -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
index 000000000000..b6df5387e855
--- /dev/null
+++ b/arch/mips/cavium-octeon/cpu.c
@@ -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);
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index be711dd2d918..cfdb4c2ac5c3 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -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");
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
index 35648302f7cc..5a5b6ba7514e 100644
--- a/arch/mips/configs/ar7_defconfig
+++ b/arch/mips/configs/ar7_defconfig
@@ -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
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index 94b7d57f906d..267bd46120bc 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -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
diff --git a/arch/mips/configs/bcm63xx_defconfig b/arch/mips/configs/bcm63xx_defconfig
index ea00c18d1f7b..7fee0273c829 100644
--- a/arch/mips/configs/bcm63xx_defconfig
+++ b/arch/mips/configs/bcm63xx_defconfig
@@ -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
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 13d9eb4736c0..c2f06e38c854 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -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
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 185df23fd460..72b7e456916e 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -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
diff --git a/arch/mips/configs/cavium-octeon_defconfig b/arch/mips/configs/cavium-octeon_defconfig
index 7afaa28a3768..c8507bc8e925 100644
--- a/arch/mips/configs/cavium-octeon_defconfig
+++ b/arch/mips/configs/cavium-octeon_defconfig
@@ -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
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 6c8cca8589ba..49e61312e006 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -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
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index dbdf3bb1a34a..68e90cd6b2d4 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -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
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index fa6814475898..90812830e940 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -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
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index d73f1de43b5d..dabf03032e06 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -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
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index ec3e028a5b2e..a15131373138 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -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
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7631dae51be9..6b64339c0014 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -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
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 9e65e6a2dcb3..cbb4d86f2912 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -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
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 1bd84d42b14f..52968c46c806 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -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
index 1995d43a2ed1..000000000000
--- a/arch/mips/configs/excite_defconfig
+++ /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
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig
index 0197f0de6b3f..a09dd03aa8c8 100644
--- a/arch/mips/configs/fuloong2e_defconfig
+++ b/arch/mips/configs/fuloong2e_defconfig
@@ -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
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index f14d38ba6034..222d7eca2fe4 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -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
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 1fc73aa7b509..ed84b4cb3c8d 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -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
diff --git a/arch/mips/configs/ip28_defconfig b/arch/mips/configs/ip28_defconfig
index 539dccb0345d..dab2e5aaadaf 100644
--- a/arch/mips/configs/ip28_defconfig
+++ b/arch/mips/configs/ip28_defconfig
@@ -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
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index d934bdefb393..1841c88d3d24 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -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
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index d22df61833a8..14c2ab3b2674 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -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
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 5380f1f582d9..4d66c44cced8 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -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
diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig
index 044074db7e55..08d481e3d42a 100644
--- a/arch/mips/configs/lasat_defconfig
+++ b/arch/mips/configs/lasat_defconfig
@@ -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
index 000000000000..b71a0a4fb95f
--- /dev/null
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -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
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 3f01870b4d65..d3c601206db2 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -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
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index d001f7e87418..6a325c02b63c 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -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
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index 7358454deaa6..f77a34e0f938 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -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
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 8c720e51795b..17203056b22b 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -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
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
index ecbc030b7b6c..000d185ddf42 100644
--- a/arch/mips/configs/msp71xx_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -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
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 9477f040796d..144b94d9a6ad 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -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
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index be8091ef0a79..ddf67f639194 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -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
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index e74ba794c789..5ec60836b645 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -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
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 1d896fd830da..6647642b5d97 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -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
diff --git a/arch/mips/configs/pnx8335-stb225_defconfig b/arch/mips/configs/pnx8335-stb225_defconfig
index fef4d31c2055..848344d588d1 100644
--- a/arch/mips/configs/pnx8335-stb225_defconfig
+++ b/arch/mips/configs/pnx8335-stb225_defconfig
@@ -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
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index e10c7116c3c2..9d721fdccb30 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -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
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index 5ed3c8dfa0a1..ab07ec08c6fa 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -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
index 000000000000..7291633d81cc
--- /dev/null
+++ b/arch/mips/configs/powertv_defconfig
@@ -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
diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig
index f40c3a04739d..57a50483abdf 100644
--- a/arch/mips/configs/rb532_defconfig
+++ b/arch/mips/configs/rb532_defconfig
@@ -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
diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig
index 6c6a19aebe1f..21c2022d46ee 100644
--- a/arch/mips/configs/rbtx49xx_defconfig
+++ b/arch/mips/configs/rbtx49xx_defconfig
@@ -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
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index e53b8d096cfc..790362890033 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -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
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 7f38c0b956f3..7f07bf02b838 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -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
#
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index b5059881bc7e..c54d1128f9a3 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -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
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b06a716bf23f..e7c5cd32a2bd 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -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
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 46512cf7ce04..b50032ba4d01 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -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
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index b437eb7f8672..c02ba08b69ab 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -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
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 06acc7482e4c..a35bc41389e5 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -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
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 69feaf88b510..e3d68d651e7d 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -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
diff --git a/arch/mips/fw/arc/cmdline.c b/arch/mips/fw/arc/cmdline.c
index 4ca4eef934a5..5c8603c85f20 100644
--- a/arch/mips/fw/arc/cmdline.c
+++ b/arch/mips/fw/arc/cmdline.c
@@ -16,11 +16,6 @@
#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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/mips/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index f5dfaf6a1606..09eee09780f2 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -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
index 000000000000..83894aa7932c
--- /dev/null
+++ b/arch/mips/include/asm/clock.h
@@ -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
index 000000000000..6b04c98b7fad
--- /dev/null
+++ b/arch/mips/include/asm/cop2.h
@@ -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 */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 4b96d1a36056..cf373a95fe4a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -154,6 +154,8 @@
#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
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h
index 7c6681aa2ab8..e482fe90fe88 100644
--- a/arch/mips/include/asm/fcntl.h
+++ b/arch/mips/include/asm/fcntl.h
@@ -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
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 8a3ef247659a..7fcef8ef3fab 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -28,15 +28,7 @@
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 *);
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index e5189572956c..aecada6f6117 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -25,17 +25,27 @@
#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);
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 40a8c178f10d..3986cd8704f3 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -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 */
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 09b08d05ff72..06960364c96b 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -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
index 107104c3cd12..000000000000
--- a/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h
+++ /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
index 4c29ba44992c..000000000000
--- a/arch/mips/include/asm/mach-excite/excite.h
+++ /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
index 0a1ef69bece7..000000000000
--- a/arch/mips/include/asm/mach-excite/excite_fpga.h
+++ /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
index c4cf6140622e..000000000000
--- a/arch/mips/include/asm/mach-excite/excite_nandflash.h
+++ /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
index 94705a46f72e..000000000000
--- a/arch/mips/include/asm/mach-excite/rm9k_eth.h
+++ /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
index 3fa3c08d2da7..000000000000
--- a/arch/mips/include/asm/mach-excite/rm9k_wdt.h
+++ /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
index 009577734a8d..000000000000
--- a/arch/mips/include/asm/mach-excite/rm9k_xicap.h
+++ /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
index 000000000000..021f77ca59ec
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
@@ -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
index 000000000000..4b493d6772c2
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
@@ -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
index 000000000000..0dca9c89ee7c
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
@@ -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
index 000000000000..6305bea7e18e
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
@@ -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 */
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 71a6851ba833..981c75f91a7d 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -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,
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index da70bcf2304e..ee8bc8376972 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -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 */
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 206ea2067916..acf8359cb135 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -13,10 +13,15 @@
#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 */
diff --git a/arch/mips/include/asm/mach-loongson/mem.h b/arch/mips/include/asm/mach-loongson/mem.h
index bd7b3cba7e35..e9960f341b96 100644
--- a/arch/mips/include/asm/mach-loongson/mem.h
+++ b/arch/mips/include/asm/mach-loongson/mem.h
@@ -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
@@ -12,19 +12,30 @@
#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 */
diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
index f1663ca81da0..a199a4f6de4e 100644
--- a/arch/mips/include/asm/mach-loongson/pci.h
+++ b/arch/mips/include/asm/mach-loongson/pci.h
@@ -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
@@ -22,16 +23,39 @@
#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
index 000000000000..bcad43a93ebf
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/asic.h
@@ -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
index 000000000000..9a65c93782f9
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/asic_regs.h
@@ -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
index 000000000000..5b8d5ebeb838
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -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
index 000000000000..629a57413657
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/interrupts.h
@@ -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
index 000000000000..e6276d5146e8
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/ioremap.h
@@ -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
index 000000000000..4bd5d0c61a91
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/irq.h
@@ -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
index 000000000000..6f3e9a0fcf8c
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/powertv-clock.h
@@ -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
diff --git a/arch/mips/include/asm/mach-excite/war.h b/arch/mips/include/asm/mach-powertv/war.h
index 1f82180c1598..7ac05ecc512b 100644
--- a/arch/mips/include/asm/mach-excite/war.h
+++ b/arch/mips/include/asm/mach-powertv/war.h
@@ -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
@@ -14,12 +17,12 @@
#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 */
diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h
index a576ce044c3c..d14e2adc4be5 100644
--- a/arch/mips/include/asm/mips-boards/bonito64.h
+++ b/arch/mips/include/asm/mips-boards/bonito64.h
@@ -26,11 +26,6 @@
/* 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
/*
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 6083db586500..145bb81ccaa5 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,6 +24,33 @@
#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
index 000000000000..ec94b9ab7be1
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-agl-defs.h
@@ -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
index 000000000000..dab6dca492f9
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h
@@ -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
index 000000000000..9ae45fcbe3e3
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-smix-defs.h
@@ -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
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index cac9b1a206fc..4d0a8c61fc3e 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -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);
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index d6eb6134abec..1854336e56a2 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -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.
*/
diff --git a/arch/mips/include/asm/sgialib.h b/arch/mips/include/asm/sgialib.h
index bfce5c786f1c..63741ca1e422 100644
--- a/arch/mips/include/asm/sgialib.h
+++ b/arch/mips/include/asm/sgialib.h
@@ -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. */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index db0fa7b5aeaf..3b6da3330e32 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -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)
@@ -62,10 +59,17 @@
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
@@ -83,15 +87,19 @@
#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
@@ -107,11 +115,7 @@
.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
@@ -166,7 +170,6 @@
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
@@ -178,20 +181,21 @@
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
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index eecd2a9f155c..9326af5186fe 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -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)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 7a51866068a4..80e202eca056 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -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
index 000000000000..58c601eee6fd
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Kconfig
@@ -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
index 000000000000..c3479a432efe
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Makefile
@@ -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
index 000000000000..d7ca256e33ef
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_clock.c
@@ -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
index 000000000000..2f6a0b147ab8
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -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
index 000000000000..a27c16c8690e
--- /dev/null
+++ b/arch/mips/kernel/csrc-powertv.c
@@ -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
index 000000000000..68b067040d8b
--- /dev/null
+++ b/arch/mips/kernel/ftrace.c
@@ -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 */
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 8b0b4181219f..981f86c26168 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -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
index 000000000000..0a9cfdb271dd
--- /dev/null
+++ b/arch/mips/kernel/mcount.S
@@ -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
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 225755d0c1f6..1d04807874db 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -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
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 2b290d70083e..f9513f9e61d3 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -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;
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 6254041b942f..d0c68b5d717b 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -35,6 +35,15 @@
#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);
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 2e74075ac0ca..03abaf048f09 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -35,6 +35,15 @@
#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);
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index e72e6844d134..6cdca1956b77 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -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();
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a38e3ee95515..23499b5bd9c3 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -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:
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0a18b4c62afb..308e43460864 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -25,10 +25,12 @@
#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);
}
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 67bd626942ab..69b039ca8d83 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -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
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 162b29954baa..f25df73db923 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -46,6 +46,7 @@ SECTIONS
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
+ IRQENTRY_TEXT
*(.text.*)
*(.fixup)
*(.gnu.warning)
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index 0bb6037afba3..8e388da1926f 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -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;
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
index 6acc6cb85f0a..20fde19a5fbf 100644
--- a/arch/mips/lasat/prom.c
+++ b/arch/mips/lasat/prom.c
@@ -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 */
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 14b9a28a4aec..d87ffd04cb0a 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -204,7 +204,7 @@ static ctl_table lasat_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_lasat_prid,
-. },
+ },
#ifdef CONFIG_INET
{
.procname = "ipaddr",
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index d45092505fa1..3df1967dea08 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -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
diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
index 39048c455d7d..2b76cb0fb07d 100644
--- a/arch/mips/loongson/Makefile
+++ b/arch/mips/loongson/Makefile
@@ -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/
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index 656b3cc0a2a6..7668c4de1151 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -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
diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson/common/bonito-irq.c
index 3e31e7ad713e..2dc2a4cc632a 100644
--- a/arch/mips/loongson/common/bonito-irq.c
+++ b/arch/mips/loongson/common/bonito-irq.c
@@ -12,18 +12,19 @@
* 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
}
diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c
index 75f1b243ee4e..7ad47f227477 100644
--- a/arch/mips/loongson/common/cmdline.c
+++ b/arch/mips/loongson/common/cmdline.c
@@ -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
index 000000000000..510d4cdc2378
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/Makefile
@@ -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
index 000000000000..b49485f187e0
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_acc.c
@@ -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
index 000000000000..74f9c59d36af
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
@@ -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
index 000000000000..3f61594b3884
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c
@@ -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
index 000000000000..b6f17f538e48
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c
@@ -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
index 000000000000..6cb44dbaeec2
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
@@ -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
index 000000000000..8fdb02b6e90f
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
@@ -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
index 000000000000..e23f3d7d2c1d
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_pci.c
@@ -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;
+}
diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c
index bc73edc0cfd8..23e7a8f8897f 100644
--- a/arch/mips/loongson/common/early_printk.c
+++ b/arch/mips/loongson/common/early_printk.c
@@ -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
@@ -12,26 +12,29 @@
#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);
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index b9ef50385541..196d947d929a 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -17,11 +17,14 @@
* 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 */
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index 3abe927422a3..a2abd9355737 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -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
@@ -10,19 +10,28 @@
#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)
diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c
index b32b4a3e5137..20e732831978 100644
--- a/arch/mips/loongson/common/irq.c
+++ b/arch/mips/loongson/common/irq.c
@@ -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();
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 7b348248de7d..0ed52b3f5314 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -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);
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index e94ef158f980..ceacd092b446 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -12,15 +12,40 @@
#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 */
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index a3a4abfb6c9a..31d8c5ecd16c 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -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
index 000000000000..be81777eb94d
--- /dev/null
+++ b/arch/mips/loongson/common/platform.c
@@ -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
index 000000000000..b625fec8a4d5
--- /dev/null
+++ b/arch/mips/loongson/common/pm.c
@@ -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);
diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
index 97e918251edd..d57f1719da95 100644
--- a/arch/mips/loongson/common/reset.c
+++ b/arch/mips/loongson/common/reset.c
@@ -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
index 000000000000..23b66a5f88cb
--- /dev/null
+++ b/arch/mips/loongson/common/serial.c
@@ -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);
diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson/common/time.c
index 6e08c8270abe..35f0b66a94f5 100644
--- a/arch/mips/loongson/common/time.c
+++ b/arch/mips/loongson/common/time.c
@@ -14,11 +14,14 @@
#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
index 000000000000..78ff66ae749e
--- /dev/null
+++ b/arch/mips/loongson/common/uart_base.c
@@ -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);
+}
diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c
index 7888cf69424a..320e9379bdd7 100644
--- a/arch/mips/loongson/fuloong-2e/irq.c
+++ b/arch/mips/loongson/fuloong-2e/irq.c
@@ -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)
diff --git a/arch/mips/loongson/fuloong-2e/reset.c b/arch/mips/loongson/fuloong-2e/reset.c
index 677fe186db95..fc16c677d476 100644
--- a/arch/mips/loongson/fuloong-2e/reset.c
+++ b/arch/mips/loongson/fuloong-2e/reset.c
@@ -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
index 000000000000..4d84b27dc41b
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/Makefile
@@ -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
index 000000000000..4d84111a2cd4
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
@@ -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
index 000000000000..1595a21b315b
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.h
@@ -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
index 000000000000..77d32f9cf31e
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/irq.c
@@ -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
index 000000000000..d7af2e616592
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/pm.c
@@ -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
index 000000000000..51d1a60d5349
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/reset.c
@@ -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;
+ }
+}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 454b53924490..8f2f8e9d8b21 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -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);
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index df7b9d928efc..36d975ae08f8 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -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;
}
diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile
index 57f43c1c7882..41b96571315e 100644
--- a/arch/mips/mipssim/Makefile
+++ b/arch/mips/mipssim/Makefile
@@ -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
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index 2877675c5f0d..0824f6af4777 100644
--- a/arch/mips/mipssim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -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
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index 1bd1f18ac23c..3571090ba178 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -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);
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 8d1f4f363049..9e8d00389eef 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -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 ...
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index bb1719a55d22..3d0baa4a842d 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -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:
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index f467199676a8..0a165c5179a1 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -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)
diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h
index c6d1e3dd82d4..3d153edaa51e 100644
--- a/arch/mips/mm/uasm.h
+++ b/arch/mips/mm/uasm.h
@@ -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 {
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 9035c64bc5ed..b27419c84919 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -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");
diff --git a/arch/mips/nxp/pnx833x/common/interrupts.c b/arch/mips/nxp/pnx833x/common/interrupts.c
index 30533ba200e2..3a467c04f811 100644
--- a/arch/mips/nxp/pnx833x/common/interrupts.c
+++ b/arch/mips/nxp/pnx833x/common/interrupts.c
@@ -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,
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c
index 575cd1473475..475ff46712ab 100644
--- a/arch/mips/oprofile/op_model_loongson2.c
+++ b/arch/mips/oprofile/op_model_loongson2.c
@@ -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;
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 91bfe73a7f60..c9209ca6c8e7 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -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
index cd64d9f177c4..000000000000
--- a/arch/mips/pci/fixup-excite.c
+++ /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;
-}
diff --git a/arch/mips/pci/fixup-fuloong2e.c b/arch/mips/pci/fixup-fuloong2e.c
index 0c4c7a81213f..4f6d8da07f93 100644
--- a/arch/mips/pci/fixup-fuloong2e.c
+++ b/arch/mips/pci/fixup-fuloong2e.c
@@ -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
index 000000000000..caf2edeb02f0
--- /dev/null
+++ b/arch/mips/pci/fixup-lemote2f.c
@@ -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);
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index 54e55e7a2431..1b3e03f20c54 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,13 +29,8 @@
#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
index 000000000000..aa5d3da27212
--- /dev/null
+++ b/arch/mips/pci/ops-loongson2.c
@@ -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
index 8a56876afcc6..000000000000
--- a/arch/mips/pci/pci-excite.c
+++ /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
index 000000000000..ff0e7e3e6954
--- /dev/null
+++ b/arch/mips/powertv/Kconfig
@@ -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
index 000000000000..2c516718affe
--- /dev/null
+++ b/arch/mips/powertv/Makefile
@@ -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
index 000000000000..2016bfe94d66
--- /dev/null
+++ b/arch/mips/powertv/asic/Kconfig
@@ -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
index 000000000000..bebfdcff0443
--- /dev/null
+++ b/arch/mips/powertv/asic/Makefile
@@ -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
index 000000000000..03d3884c6270
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-calliope.c
@@ -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
index 000000000000..5f4589c9f83d
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-cronus.c
@@ -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
index 000000000000..1469daab920e
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-zeus.c
@@ -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
index 000000000000..bae82880b6b5
--- /dev/null
+++ b/arch/mips/powertv/asic/asic_devices.c
@@ -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
index 000000000000..80b2eed21ac3
--- /dev/null
+++ b/arch/mips/powertv/asic/asic_int.c
@@ -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
index 000000000000..b54d24499b06
--- /dev/null
+++ b/arch/mips/powertv/asic/irq_asic.c
@@ -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
index 000000000000..cd5b76a1c951
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-calliope.c
@@ -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
index 000000000000..45a5c3ea718c
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-cronus.c
@@ -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
index 000000000000..23a905613c04
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-cronuslite.c
@@ -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
index 000000000000..018d4514dbe3
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-zeus.c
@@ -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
index 000000000000..98d73cb0d452
--- /dev/null
+++ b/arch/mips/powertv/cmdline.c
@@ -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
index 000000000000..5f4e4c304e48
--- /dev/null
+++ b/arch/mips/powertv/init.c
@@ -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
index 000000000000..7af6bf25008c
--- /dev/null
+++ b/arch/mips/powertv/init.h
@@ -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
index 000000000000..28d06605fff6
--- /dev/null
+++ b/arch/mips/powertv/memory.c
@@ -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
index 000000000000..f5c62462fc9d
--- /dev/null
+++ b/arch/mips/powertv/pci/Makefile
@@ -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
index 000000000000..726bc2e824b3
--- /dev/null
+++ b/arch/mips/powertv/pci/fixup-powertv.c
@@ -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
index 000000000000..1b5886bbd759
--- /dev/null
+++ b/arch/mips/powertv/pci/powertv-pci.h
@@ -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
index 000000000000..d94c54311485
--- /dev/null
+++ b/arch/mips/powertv/powertv-clock.h
@@ -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
index 000000000000..bd8ebf128f29
--- /dev/null
+++ b/arch/mips/powertv/powertv_setup.c
@@ -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
index 000000000000..494c652c984b
--- /dev/null
+++ b/arch/mips/powertv/reset.c
@@ -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
index 000000000000..888fd09e2620
--- /dev/null
+++ b/arch/mips/powertv/reset.h
@@ -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
diff --git a/arch/mips/mipssim/sim_cmdline.c b/arch/mips/powertv/time.c
index 74240e1ce5a5..1e0a5ef4c8c7 100644
--- a/arch/mips/mipssim/sim_cmdline.c
+++ b/arch/mips/powertv/time.c
@@ -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
@@ -14,19 +16,22 @@
* 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();
}
diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c
index ad5bd1097974..d7c26d00cfef 100644
--- a/arch/mips/rb532/prom.c
+++ b/arch/mips/rb532/prom.c
@@ -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);
}
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index 1617241d2737..da44ccb20829 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -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++) {
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index 0ecd5fe9486e..383f11d7f442 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -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;
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index b9a931358e23..5deeb68b6c9c 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -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);
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index c8f7d2328b24..603fc91c1030 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -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;
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index c5a5d4a31b4b..3abd1465ec02 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -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);
diff --git a/arch/mips/sibyte/common/cfe.c b/arch/mips/sibyte/common/cfe.c
index eb5396cf81bb..6343011e9902 100644
--- a/arch/mips/sibyte/common/cfe.c
+++ b/arch/mips/sibyte/common/cfe.c
@@ -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();
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 7dd76fb3b645..e6980892834a 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -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,
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 74e6c67982fb..51e62bbaa23b 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -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,
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 071a9573ac7f..f4699d35858b 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -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,
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 5e687819cbc2..46f00691f448 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -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,
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index a49272ce7ef5..d16b462154c3 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -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) {
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index d66802edebb2..06e801c7e258 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/mn10300/include/asm/asm-offsets.h
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/parisc/include/asm/asm-offsets.h
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/powerpc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index bcc69e1f77c1..45c0cb9b67e6 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -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>
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
index 9290a7a442d0..fb4eb0df054c 100644
--- a/arch/powerpc/platforms/amigaone/setup.c
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -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>
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index b93f877ba504..b9d5d678aa44 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -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
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 52f3df3b4ca0..8f41685d8f42 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -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>
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index cf660916ae0b..9dd789a7370d 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/s390/include/asm/asm-offsets.h
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/score/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/score/include/asm/cacheflush.h b/arch/score/include/asm/cacheflush.h
index caaba24036e3..1d545d0ce206 100644
--- a/arch/score/include/asm/cacheflush.h
+++ b/arch/score/include/asm/cacheflush.h
@@ -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)
diff --git a/arch/score/include/asm/delay.h b/arch/score/include/asm/delay.h
index 6726ec199dc0..529e494712a5 100644
--- a/arch/score/include/asm/delay.h
+++ b/arch/score/include/asm/delay.h
@@ -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. */
diff --git a/arch/score/include/asm/page.h b/arch/score/include/asm/page.h
index d92a5a2d36d4..1e9ade8e77e6 100644
--- a/arch/score/include/asm/page.h
+++ b/arch/score/include/asm/page.h
@@ -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)
diff --git a/arch/score/kernel/setup.c b/arch/score/kernel/setup.c
index 6a2503c75c4e..6f898c057878 100644
--- a/arch/score/kernel/setup.c
+++ b/arch/score/kernel/setup.c
@@ -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,
diff --git a/arch/score/mm/cache.c b/arch/score/mm/cache.c
index dbac9d9dfddd..b25e95743600 100644
--- a/arch/score/mm/cache.c
+++ b/arch/score/mm/cache.c
@@ -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);
}
}
diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c
index 4e3dcd0c4716..8c15b2c85d5a 100644
--- a/arch/score/mm/init.c
+++ b/arch/score/mm/init.c
@@ -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),
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index ac17c5ac550e..db91925c79d1 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -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
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 052b354236dc..7898f14d6641 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -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
index 378db779fb6c..000000000000
--- a/arch/sh/include/asm/.gitignore
+++ /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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/sh/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index 84dd37761f56..9c30955630ff 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -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);
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
index 567516b58acc..558a56bcc7cf 100644
--- a/arch/sh/tools/Makefile
+++ b/arch/sh/tools/Makefile
@@ -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; }
diff --git a/arch/sh/tools/gen-mach-types b/arch/sh/tools/gen-mach-types
index 65161e368353..f5ff7c5d8913 100644
--- a/arch/sh/tools/gen-mach-types
+++ b/arch/sh/tools/gen-mach-types
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/sparc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h
index 3b9cfb39175e..38f37b333cc7 100644
--- a/arch/sparc/include/asm/fcntl.h
+++ b/arch/sparc/include/asm/fcntl.h
@@ -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
diff --git a/arch/um/Makefile b/arch/um/Makefile
index fc633dbacf84..fab8121d2b32 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/um/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b31cc54b4641..93e689f4bd86 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -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>
diff --git a/arch/x86/boot/version.c b/arch/x86/boot/version.c
index 2723d9b5ce43..2b15aa488ffb 100644
--- a/arch/x86/boot/version.c
+++ b/arch/x86/boot/version.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/x86/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 2779321046bd..017d937639fe 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -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
index 000000000000..d370ee36a182
--- /dev/null
+++ b/arch/xtensa/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index d672cfe7ca59..cb423f5aef24 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -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>
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index 27ae750ca878..bf31592eaf79 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -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
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 95ccbe377f9c..46c3c566307e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -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
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 33c2ee105284..450c8e894277 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -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
index 000000000000..d8a26d16d948
--- /dev/null
+++ b/drivers/hwmon/k10temp.c
@@ -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
index 000000000000..dc1f5402c1d7
--- /dev/null
+++ b/drivers/hwmon/lis3lv02d_i2c.c
@@ -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);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index ebe38b680ee3..864a371f6eb9 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -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;
}
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 8ad50fdba00d..9ca97818bd4b 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -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
index 000000000000..7442cf754856
--- /dev/null
+++ b/drivers/hwmon/via-cputemp.c
@@ -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)
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index b257c7223733..38e280523071 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -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);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e4f599f20e38..8a0e1ec95e4a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -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
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 46d72704d606..9e63869d7c0d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -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
index 000000000000..a8f315902131
--- /dev/null
+++ b/drivers/leds/leds-adp5520.c
@@ -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");
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c
index 731d4eef3425..f59ffadf5125 100644
--- a/drivers/leds/leds-alix2.c
+++ b/drivers/leds/leds-alix2.c
@@ -11,11 +11,24 @@
#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);
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 8816806accd2..da5fb016b1a5 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -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;
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index defc212105f3..438d48384636 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -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
index 000000000000..fee40a841959
--- /dev/null
+++ b/drivers/leds/leds-lt3593.c
@@ -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");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index cdfdc8714e10..88b1dd091cfb 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -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
index 000000000000..7f00de3ef922
--- /dev/null
+++ b/drivers/leds/leds-regulator.c
@@ -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
index 000000000000..97f04984c1ca
--- /dev/null
+++ b/drivers/leds/leds-ss4200.c
@@ -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);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 610e914abe6c..85bc6a685e36 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -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;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1a7a9fc50ea1..e3551d20464f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -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
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index e9eae4a78402..1eac626e710a 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -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 [] = {
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index cdb845b68ab5..06b64085a355 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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;
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d37464e296a5..9e060c87e64d 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -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);
}
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9d405b181781..ce1d28884e29 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -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.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index ded4d8cdd9d7..3d253dd4240f 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -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
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of-core.c
index 01ab916c2802..55e33135edb4 100644
--- a/drivers/mmc/host/sdhci-of.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -22,62 +22,37 @@
#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
index 000000000000..d5b11a17e648
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -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
index 000000000000..35117f3ed757
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -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
index 000000000000..ad09ad9915d8
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of.h
@@ -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 */
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index ce5f1d73dc04..842f46f94284 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -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 */
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 74fa075c838a..b13f6417b5b2 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -20,14 +20,23 @@
#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 {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 7678538344f4..677cd53f18c3 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -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
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 460a1f39a8d1..1407bd144015 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -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
index af6a6a5399e1..000000000000
--- a/drivers/mtd/nand/excite_nandflash.c
+++ /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)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a5be9ac6405c..e58a65391ad2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1953,6 +1953,8 @@ config BCM63XX_ENET
source "drivers/net/fs_enet/Kconfig"
+source "drivers/net/octeon/Kconfig"
+
endif # NET_ETHERNET
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 246323d7f161..ad1346dd9da9 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -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
index 000000000000..1e56bbf3f5c0
--- /dev/null
+++ b/drivers/net/octeon/Kconfig
@@ -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
index 000000000000..906edecacfd3
--- /dev/null
+++ b/drivers/net/octeon/Makefile
@@ -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
index 000000000000..050538bf155a
--- /dev/null
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -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);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d5d8e1c5bc91..fc5938ba3d78 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -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
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index edfaac48cbd5..1342585af381 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -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
index 000000000000..61a4461cbda5
--- /dev/null
+++ b/drivers/net/phy/mdio-octeon.c
@@ -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");
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 675b7df632fc..27ca859e7453 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -63,7 +63,7 @@
#ifndef __iwl_core_h__
#define __iwl_core_h__
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
/************************
* forward declarations *
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 3aabf1e37988..76e640bccde8 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -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;
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 11003bba10d3..1a387e79f719 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -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
index 000000000000..04719551381b
--- /dev/null
+++ b/drivers/regulator/88pm8607.c
@@ -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");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7cfdd65bebb4..262f62eec837 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -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
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 9ae3cc44e668..b3c806c79415 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -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
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 49aeee823a25..b349db4504b7 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -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);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index efe568deda12..686ef270ecf7 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -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;
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index aa224d936e0d..f8c4661a7a81 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -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;
}
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 7803a320543b..76d08c282f9c 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -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
index 000000000000..acc2fb7b6087
--- /dev/null
+++ b/drivers/regulator/max8660.c
@@ -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
index 000000000000..39c495300045
--- /dev/null
+++ b/drivers/regulator/mc13783-regulator.c
@@ -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
index 710211f67449..000000000000
--- a/drivers/regulator/mc13783.c
+++ /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");
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 7ea1c3a31081..7e674859bd59 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -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
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 2eefc1a0cf08..0a6577577e8d 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -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;
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 902db56ce099..61e02ac2fda3 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -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)
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index eb154dc57164..c8c12325e69b 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -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.
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 259db7f3535b..9630e7d3314e 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -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 */
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 8a99da6f2f24..c4ec5c158aa1 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -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);
}
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 713f7bf5afb3..5317bbcbc7a0 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -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,
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3bf75924741f..84d3bbaa95e7 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -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>
@@ -100,7 +101,7 @@
#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;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 36900c71a592..9191d1ea6451 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -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
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 280d3c657d60..92a8c500b23d 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -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
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 698a527d6cca..f008708f1b08 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -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);
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 2b973f3c2eb2..6cf9dc37d78b 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -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;
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 5c8d7630c13e..1af578dec276 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -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;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 0c4210d48ee8..6d8172e781cf 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -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);
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 132898c88d5e..33b2294625bb 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -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);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
index c1d5be4adf9c..26ffdcd5a437 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
@@ -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;
}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
index 709105071177..1fe3b0f1f3c9 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
@@ -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;
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 47cfe1c49c3e..1a660191a905 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -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"},
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 51c24b37c60a..10be9f36a4cc 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -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);
}
@@ -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
index 000000000000..bb96fdd58e23
--- /dev/null
+++ b/drivers/scsi/hpsa.c
@@ -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
index 000000000000..6bd1949144b5
--- /dev/null
+++ b/drivers/scsi/hpsa.h
@@ -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
index 000000000000..12d71387ed9a
--- /dev/null
+++ b/drivers/scsi/hpsa_cmd.h
@@ -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 */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8643f5089361..9e52d16c7c39 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -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) {
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index c4b58d042f6f..881d5dfe8c74 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -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) {
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 74338c83ad0a..0b165024a219 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -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);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 35ca0e72df46..02300523b234 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -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);
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 226920d15ea1..d4da6bdd0e73 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -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
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 134c63ef6d38..99ff99e45bee 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -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");
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 6422e258fd52..89d02401b9ec 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -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;
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index c790d45876c4..cae6b2cf492f 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -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 */
};
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 950202a70bcf..24223473f573 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -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;
}
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index 22644de26399..63ad4aa0c422 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -45,16 +45,6 @@
#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
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a3de306b9045..9b44c6f1b10e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -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 =
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 96e4daa68b8f..833a5201eda4 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -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)));
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 42ebe725d5a5..c2f1032496cb 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -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));
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 1f767a0e727a..7f9c83a76390 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -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 ,
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 30f2ede55a75..8e38ca8cd101 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -59,11 +59,11 @@
#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
*/
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 34c6b896a91b..e7d2688fbeba 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -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;
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index 2752b56cad56..92f89d50850c 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -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
@@ -106,7 +109,7 @@
#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
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6b9bf23c7735..384afda7dbe9 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -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))
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e21851358509..0b6801fc6389 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -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;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b74924b279ef..73a793539d45 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -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);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 804987397b77..1692a883f4de 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -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;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index a47d34308a3a..2a4c7f4e7b69 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -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);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 41669357b186..2f873d237325 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -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);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 807e0dbc67fa..c482220f7eed 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -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
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e495d3813948..d8927681ec88 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -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:
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6531c91501be..ddfcecd5099f 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -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)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 9093c7261f33..255da53e5a01 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -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);
}
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index e374804d26fb..43d3caf268ef 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -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)
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index ad59abb47722..d04ea9a6f673 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -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;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 544dc6b1f548..f91a67c6d968 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -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;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2d9d70359360..f55eb0107336 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -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.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ed8c1675b52f..f3d2810ba11c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -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)
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index f5b3fdbb1e27..d21c24eaf0a9 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -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
index 000000000000..31620fae77be
--- /dev/null
+++ b/drivers/spi/dw_spi.c
@@ -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
index 000000000000..34ba69161734
--- /dev/null
+++ b/drivers/spi/dw_spi_pci.c
@@ -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");
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 73e24ef5a2f9..1d41058bbab2 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -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;
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index e9390d747bfc..1fb2a6ea328c 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -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;
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 276591569c8b..c010733877ae 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -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
@@ -28,6 +28,11 @@
#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
index 000000000000..3793cae361db
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx_fiq.S
@@ -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
index 000000000000..a5950bb25b51
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx_fiq.h
@@ -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
index 000000000000..88a456dba967
--- /dev/null
+++ b/drivers/spi/spi_s3c64xx.c
@@ -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");
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c
index 7d36720eb982..a65c12ffa733 100644
--- a/drivers/spi/spi_sh_sci.c
+++ b/drivers/spi/spi_sh_sci.c
@@ -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;
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index 19f75627c3de..dfa024b633e1 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -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;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 9c446e6003d5..ea1bec3c9a13 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -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);
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index f0b86f02cd80..fd677f008365 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -29,7 +29,6 @@
* driver requests - some may support multiple options */
-#include <linux/autoconf.h>
#include "iio.h"
#include "ring_generic.h"
diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig
index 536e2382de54..638ad6b35891 100644
--- a/drivers/staging/octeon/Kconfig
+++ b/drivers/staging/octeon/Kconfig
@@ -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
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 31a58e508924..05a5cc0f43ed 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -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>
@@ -34,86 +35,12 @@
#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;
}
diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h
index b3328aeec2df..55d0614a7cd9 100644
--- a/drivers/staging/octeon/ethernet-mdio.h
+++ b/drivers/staging/octeon/ethernet-mdio.h
@@ -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);
diff --git a/drivers/staging/octeon/ethernet-proc.c b/drivers/staging/octeon/ethernet-proc.c
index 8fa88fc419b7..16308d484d3b 100644
--- a/drivers/staging/octeon/ethernet-proc.c
+++ b/drivers/staging/octeon/ethernet-proc.c
@@ -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>
@@ -38,112 +37,6 @@
#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;
}
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index fbaa465d2fac..3820f1ec11d1 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -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);
+ }
}
}
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c
index 2b54996bd85d..6061d01eca2d 100644
--- a/drivers/staging/octeon/ethernet-sgmii.c
+++ b/drivers/staging/octeon/ethernet-sgmii.c
@@ -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 */
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c
index 0c2e7cc40f35..ee3dc41b2c53 100644
--- a/drivers/staging/octeon/ethernet-xaui.c
+++ b/drivers/staging/octeon/ethernet-xaui.c
@@ -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;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 492c5029992d..4cfd4b136b32 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -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))
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index 3aef9878fc0a..402a15b9bb0e 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -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 */
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 4ce399b6d237..f98a52448eae 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -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>
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 12f1ad2fd0e8..74d07f4e8b7d 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -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
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 2051c9dc813b..b7687c55fe16 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -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);
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 4c10edecfb66..86d95c228adb 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index 2c3bdfc620b7..d769b0bab21a 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -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,
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index 2cf7ba52f67c..f625ffc69ad3 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 6615ac7fa60a..18829cf68b1b 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -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;
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 96774949cd30..b4bcf8043797 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -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,
};
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index b9fe62b475c6..da86db4374a0 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -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,
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index f2d76dae1eb3..74cdc640173d 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 6d27f62fdcd0..e6d348e63596 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -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,
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 7fb4eefff80d..f7cc528d5be7 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 7aed2565c1bd..db9071fc5665 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -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,
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index a38fda1742dd..939e7b830cf3 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 6b488b8a7eee..00a9591b0003 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -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,
};
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 9edb8d7c295f..2e78b0784bdc 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -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."),
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 8693e5fcd2eb..409ca9643528 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 9edaf24fd82d..075786e05034 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 887166267443..9d2ec2a1cce8 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -22,8 +22,10 @@
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;
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 43edbada12d1..e14ce4d469f5 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -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,
};
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 467bdb7efb23..e32add37a203 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -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,
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
index 5bb7f6f14601..0f5952cae85e 100644
--- a/drivers/video/omap/lcd_ldp.c
+++ b/drivers/video/omap/lcd_ldp.c
@@ -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,
diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
index 006c2fe7360e..7e7a65c08452 100644
--- a/drivers/video/omap/lcd_omap2evm.c
+++ b/drivers/video/omap/lcd_omap2evm.c
@@ -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;
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
index fc503d8f3c24..ca75cc2a87a5 100644
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -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>
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
index ae2edc4081a8..06840da0b094 100644
--- a/drivers/video/omap/lcd_omap3evm.c
+++ b/drivers/video/omap/lcd_omap3evm.c
@@ -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;
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
index 56ee192e9ee2..564933ffac6e 100644
--- a/drivers/video/omap/lcd_overo.c
+++ b/drivers/video/omap/lcd_overo.c
@@ -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>
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 10d8c4b4baeb..d8df17a7d5fc 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -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;
}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d958b76430a2..da84fd03850f 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -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
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 89c045dc468e..475c61100069 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -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
index bb66958b9433..000000000000
--- a/drivers/watchdog/rm9k_wdt.c
+++ /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);
-
diff --git a/fs/Kconfig b/fs/Kconfig
index f8fccaaad628..64d44efad7a5 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -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"
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 94f5110c4655..2c994591f4d7 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -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;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index b639dcf7c778..346b69405363 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -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 */
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 97b6e9efeb7f..edd90c49003c 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -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;
}
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 7b055385db8e..c25256a5c5b0 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -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
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index a2796651e756..d4a00ea1054c 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -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);
}
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index eff74b9c9e77..2a9b5330cc5e 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -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
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
index 402afe0a0bfb..7bb3c020e570 100644
--- a/fs/btrfs/Kconfig
+++ b/fs/btrfs/Kconfig
@@ -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.
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 52cbe47022bf..2e9e69987a82 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -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;
}
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index f6783a42f010..3f1f50d9d916 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -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;
}
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ec96f3a6d536..c4bc570a396e 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -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;
}
/*
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 444b3e9b92a4..9f806dd04c27 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -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 */
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index f3a6075519cc..e9103b3baa49 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -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;
}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 02b6afbd7450..009e3bd18f23 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -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);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 94627c4cc193..56e50137d0e6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -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);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 77f759302e12..feaa13b105d9 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -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;
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b3ad168a0bfc..5440bab23635 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -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;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index cdbb054102b9..645a17927a8f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -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;
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 5799bc46a309..b10a49d4bc6a 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -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;
}
/*
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index f82e87488ca8..1fe1282ef47c 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -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
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index cfcc93c93a7b..a9728680eca8 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -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;
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 752a5463bf53..3f9b45704fcd 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -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;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index c207e8c32c9b..b2acc79f1b34 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -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;
}
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index d4e3e7a6938c..93c7ccb33118 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -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
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 741666a7676a..4a9434b622ec 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -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) {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 7eda483d7b5a..198cff28766d 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -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;
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index b6dd5967c48a..193b58f7d3f3 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -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);
}
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index c71e9c3cf3f7..721efa0346e0 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -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__ */
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 4012885d027f..e82adc2debb7 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -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)
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index 2dda5ade75bc..8f006a0d6076 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -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;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 056fed62d0de..429ca0b3ba08 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -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;
}
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 101fe4c7b1ee..567bc4b9f70a 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -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);
diff --git a/fs/exec.c b/fs/exec.c
index 623a5cc3076a..632b02e34ec7 100644
--- 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);
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index e5f6774846e4..9acf7e808139 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -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.
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index b192c661caa6..4dcddf83326f 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -10,7 +10,6 @@ config GFS2_FS
select SLOW_WORK
select QUOTA
select QUOTACTL
- select FS_JOURNAL_INFO
help
A cluster filesystem.
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 3ff32fa793da..6e220f4eee7d 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -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)
diff --git a/fs/inode.c b/fs/inode.c
index 06c1f02de611..03dfeb2e3928 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -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();
diff --git a/fs/jbd/Kconfig b/fs/jbd/Kconfig
index a8408983abd4..4e28beeed157 100644
--- a/fs/jbd/Kconfig
+++ b/fs/jbd/Kconfig
@@ -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
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig
index 0f7d1ceafdfd..f32f346f4b0a 100644
--- a/fs/jbd2/Kconfig
+++ b/fs/jbd2/Kconfig
@@ -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
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f26e4d03ada5..d945ea76b445 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -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
diff --git a/fs/namei.c b/fs/namei.c
index d2783c8a770b..dad4b80257db 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -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:
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index faab1273281e..7d70d63ceb29 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -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)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d5b112bcf3de..ce907efc5508 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -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;
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
index 1225af7b2166..251da07b2a1d 100644
--- a/fs/nilfs2/Kconfig
+++ b/fs/nilfs2/Kconfig
@@ -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
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 9938034762cc..dc2505abb6d7 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -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
diff --git a/fs/pipe.c b/fs/pipe.c
index 43d79da5c57e..37ba29ff3158 100644
--- 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;
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 32fae4040ebf..2efc57173fd7 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -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;
diff --git a/fs/reiserfs/Kconfig b/fs/reiserfs/Kconfig
index ac7cd75c86f8..513f431038f9 100644
--- a/fs/reiserfs/Kconfig
+++ b/fs/reiserfs/Kconfig
@@ -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.
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 3a28e7751b3c..290ae38fca8a 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -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:
diff --git a/fs/stack.c b/fs/stack.c
index 67716f6a1a4a..4a6f7f440658 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -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);
diff --git a/fs/sync.c b/fs/sync.c
index 36752a683481..418727a2a239 100644
--- 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);
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 39849f887e72..16a6444330ec 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -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.
*/
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 1d5b298ba8b2..225946012d0b 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -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;
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 0de36c2a46f1..fa402a6bbbcf 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -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)) {
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 681ddf3e844c..fcd268ce0674 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -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
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f72914db2a11..756f831cbdd5 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -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
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 0f5f57858a23..8c4f884db6b4 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -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);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index aece486ac734..cd4349bdc34e 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -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;
};
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index 90d1c2184112..9a33c5f7e126 100644
--- a/include/linux/enclosure.h
+++ b/include/linux/enclosure.h
@@ -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 */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 66bc0a54b284..cca191933ff6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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)
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index bb516ceeefc9..da317c7163ab 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -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,
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 5ed8b9c50355..abec69b63d7e 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -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 \
diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
index 3c7497d46ee9..99d9a6766f7e 100644
--- a/include/linux/kmemleak.h
+++ b/include/linux/kmemleak.h
@@ -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)
diff --git a/include/linux/leds-lp3944.h b/include/linux/leds-lp3944.h
index afc9f9fd70f5..2618aa9063bc 100644
--- a/include/linux/leds-lp3944.h
+++ b/include/linux/leds-lp3944.h
@@ -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
diff --git a/include/linux/leds-pca9532.h b/include/linux/leds-pca9532.h
index 96eea90f01a8..f158eb1149aa 100644
--- a/include/linux/leds-pca9532.h
+++ b/include/linux/leds-pca9532.h
@@ -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
index 000000000000..5a8eb389aab8
--- /dev/null
+++ b/include/linux/leds-regulator.h
@@ -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 */
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index 415c228743d5..fd322aca33ba 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -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.
*/
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
index 8a5509877192..ee24ef8ab616 100644
--- a/include/linux/mmdebug.h
+++ b/include/linux/mmdebug.h
@@ -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
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6f7561730d88..30fe668c2542 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -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>
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index d9ebf1037dfa..d74785c2393a 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -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);
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index feee2ba8d06a..5b59f35dcb8f 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -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 */
/*
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index 7a9754c96775..01b3d759f1fc 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -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);
};
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 490c5b37b6d7..030d92255c7a 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -35,6 +35,8 @@
#ifndef __LINUX_REGULATOR_CONSUMER_H_
#define __LINUX_REGULATOR_CONSUMER_H_
+#include <linux/device.h>
+
/*
* Regulator operating modes.
*
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 87f5f176d4ef..234a8476cba8 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -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
index 000000000000..9936763621c7
--- /dev/null
+++ b/include/linux/regulator/max8660.h
@@ -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
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4d7adb282bdd..e89857812be6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -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;
diff --git a/include/linux/security.h b/include/linux/security.h
index 466cbadbd1ef..2c627d361c02 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -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
index 000000000000..51b3e771a9a3
--- /dev/null
+++ b/include/linux/spi/dw_spi.h
@@ -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 */
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index 79b9837d9ca0..cf97b5b9d1fe 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -1,4 +1,4 @@
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
#include <linux/module.h>
/* Simply sanity version stamp for modules. */
diff --git a/include/linux/vt.h b/include/linux/vt.h
index 3fb9944e50a6..d5dd0bc408fd 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -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 */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 705f01fe413a..c18c008f4bbf 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -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)
{
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 39d6d1097153..a8f370126632 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -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 */
diff --git a/init/Makefile b/init/Makefile
index 4a243df426f7..0bf677aa0872 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -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)"
diff --git a/init/version.c b/init/version.c
index 52a8b98642b8..adff586401a5 100644
--- a/init/version.c
+++ b/init/version.c
@@ -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
diff --git a/kernel/bounds.c b/kernel/bounds.c
index 3c5301381837..98a51f26c136 100644
--- a/kernel/bounds.c
+++ b/kernel/bounds.c
@@ -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 */
diff --git a/kernel/exit.c b/kernel/exit.c
index 5962d7ccf243..546774a31a66 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -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;
diff --git a/kernel/fork.c b/kernel/fork.c
index 202a0ba63d3c..5b2959b3ffc2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -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)++;
}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 433e9fcc1fc5..a9a93d9ee7a7 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -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>
diff --git a/kernel/module.c b/kernel/module.c
index a65dc787a27b..e96b8ed1cb6a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -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 */
diff --git a/kernel/printk.c b/kernel/printk.c
index 1ded8e7dd19b..17463ca2e229 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -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.
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 45e4bef0012a..8a68b2448468 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -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",
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 06ba26747d7e..8b9f20ab8eed 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -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>
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8cf9938dd147..25c3ed594c54 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -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
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 735343fc857a..d4996cf46eb6 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -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
diff --git a/mm/Kconfig b/mm/Kconfig
index 43ea8c3a2bbf..ee9f3e0f2b69 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -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
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 13f33b3081ec..5b069e4f5e48 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -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>
@@ -108,7 +109,6 @@
#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 *)
@@ -119,8 +119,8 @@
/* 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);
diff --git a/mm/readahead.c b/mm/readahead.c
index aa1aa2345235..033bc135a41f 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -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);
diff --git a/mm/shmem.c b/mm/shmem.c
index f8485062f3ba..eef4ebea5158 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1830,6 +1830,8 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
iput(inode);
return error;
}
+#else
+ error = 0;
#endif
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
diff --git a/mm/slab.c b/mm/slab.c
index 7560eb00637c..7d41f15b48d3 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -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 {
diff --git a/net/socket.c b/net/socket.c
index dbfdfa96d29b..769c386bd428 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -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;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index c67e73ecd5be..ed2773edfe71 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -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)), \
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 341b58902ffc..0b94d2fa3a88 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -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)" "$(@)";
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 224d85e72ef1..cd815ac2a50b 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -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
index 000000000000..102a276f6eea
--- /dev/null
+++ b/scripts/Makefile.modbuiltin
@@ -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)
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 6bf21f83837d..ea26b23de082 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -16,15 +16,15 @@
* 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);
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
index 287467a2e8c7..8060e06798b3 100644
--- a/scripts/genksyms/keywords.c_shipped
+++ b/scripts/genksyms/keywords.c_shipped
@@ -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)
diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf
index 8fe977a4d57b..e6349acb6f2f 100644
--- a/scripts/genksyms/keywords.gperf
+++ b/scripts/genksyms/keywords.gperf
@@ -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
diff --git a/scripts/headers.sh b/scripts/headers.sh
index 0308ecc10d5b..1ddcdd38d97f 100755
--- a/scripts/headers.sh
+++ b/scripts/headers.sh
@@ -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
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 80599e3a7994..999e8a7d5bf7 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -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
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index b55e72ff2fc6..c4dec80cfd8e 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -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
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index bce3d0fe6fbd..23dbad80cce9 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -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
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 6c4ffc767b91..20923613467c 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -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. */
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index f67cc885c807..62fcc3a7f4d3 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -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/
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index b1fd48db1640..51b2aa0acb82 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -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}"
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 9cf0a6fad6ba..92f09fe9639e 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -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\$";
diff --git a/scripts/tags.sh b/scripts/tags.sh
index d52f7a01557c..1a0c44d7c4a7 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -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
}
diff --git a/scripts/unifdef.c b/scripts/unifdef.c
index 30d459fb0709..44d39785e50d 100644
--- a/scripts/unifdef.c
+++ b/scripts/unifdef.c
@@ -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
@@ -31,23 +23,20 @@
* 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
diff --git a/security/Makefile b/security/Makefile
index bb44e350c618..da20a193c8dd 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -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
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 06ec722897be..e9c2e7c584d9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -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 */
}
/*****************************************************************************/
diff --git a/security/min_addr.c b/security/min_addr.c
index fc43c9d37084..e86f297522bf 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -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();
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index c071f9603a38..3c85c0f92823 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -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);
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 83b3dde1a83b..b2b3c2d1cf8b 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -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();
}